分类:代码

码农是第一生产力。

hexo博客平台

hexo基于node.js,下载安装node.js后,用npm包管理系统安装hexo。npm有很多镜像站点可用,设置一个国内镜像可以提高下载速度。修改文件 D:nodejsnode_modulesnpmnpmrc ,增加一行:

registry = http://npm.cbyun.com/

hexo的安装使用方法官网有详细说明: http://hexo.io/

部署方法,网上讲得比较多的是github部署,如果是个人博客,要用到rsync工具。下面是 rsync配置:

deploy:
  type: rsync
  host: www.hostname.com
  user: username
  root: ~/html/hostname
  port: 22
  delete: true

用org2blog写博客

orgmode,emacs党最为推崇的笔记模式,如果不能完成写博客这样的小事情,神怎么能答应呢,于是有了org2blog这个插件。

我会告诉你我是为了用上org2blog才开通的博客么?很早就买了博客空间,但是一直苦恼没有一款好用的博客软件,于是空间一直处于闲置状态。总不能直接在网页上写博文吧,网页出错丢失内容怎么办?总不能用msn writer套件吧,谁愿意装那么大一玩意就为了编辑文本。总不能用notepad吧,格式怎么办?
有了orgmode+org2blog,这都不是问题。

org2blog的设置不多说,参考github官网就可以搞掂。使用时,可以发布整个页面,也可以发布subtree,我偏好把所有博客记录在一个文件中,每次只发布一个subtree。修改文章后,再次发布可以修改原来的文章。

说说缺点,org2blog只能push,不能pull,用其它终端发布或修改的内容不能被同步下来。作者写了个python脚本专门用来下载博客内容,没有整合到emacs中,还是有点遗憾。

博客域名和空间,用的都是goddady服务。托管空间,用的最便宜的经济型linux托管,名义上只能建一个站,实际上,通过.htaccess 文件配置,可以建多个站。我的三个站都放在这个空间里。

手机端的博客工具,目前直接用wordpress客户端软件。

字符集和编码

编码

代码页

  • 代码页即编码的值,同样的字符,在不同的代码页中,值是不同的;
  • 最常用的代码页有 GBK,BIG5,UTF-8,UTF-16;
  • GBK 是 GB2312 的扩展,代码页都是 CP936
  • GB18030 是 GBK 的扩展,代码页是 CP54936 , 一般低端设备不会支持这么全的编码;
  • GB18030,GBK,GB2312 是向下兼容的,即同一字符的值在不同编码中都相同;
  • BIG5 是繁体字的代码页;

编码格式

  • GBK 只有一种编码方案,ascii 码占一个字符,中文字符占两个字节;
  • UNICODE 有三种编码方案:UTF-8,UTF-16,UTF-32;
    • 通常所说的 UNICODE 是指 UTF-16 编码方案,UTF-8,UTF-32 需要特指;
    • UTF-8 字符是以 8 位序列来编码的,用一个或几个字节来表示一个字符,ASCII 码占一个字节;
    • UTF-16UTF-32 分别是 UNICODE 的 16 位和 32 位编码方式;

编码转换

  • GBK 等与 UTF-8 之间都必须通过 Unicode 编码(即 UTF-16)才能相互转换;

编程相关

char / wchar_t

  • 定义 char * 类形的窄字符串时,采用的是内码编码,即源文件的编码。在 Windows 中文系统下即 GBK 编码,因为文本文件默认以 GBK 编码保存;
  • 定义 wchar_t * 类型宽的字符串时,采用的 UNICODE 编码,在 Windows 中文系统下即 UTF-16 格式,在 Linux 下采用 UTF-32 格式;

string / wstring

  • string 一般用来存储 GBK, UTF-8 编码;
  • wstring 一般用来存储 UTF-16 编码;
  • 通常用到的 string2wstring 编码转换即 GBK->UNICODE;wstirng2string 即 UNICODE->GBK;

printf / wprintf

  • printf 格式化输出 %s 时,可输出 GBK 编码;格式化输出 %S%ws 时,可输出 UNICODE 编码;
  • wprintf 格式化输出 %s 时,可输出 UNICODE 编码;格式化输出 %S%ws 时,可输出 GBK 编码;

OS 相关

系统内码

  • Windows 中文系统默认的内码是 GBK ,即以 GBK 解析字节流;
  • Linux 系统默认的内码是 UTF-8 ,即以 UTF-8 解析字节流;

内部存储

  • Windows 中 UNICODE 默认采用 UTF-16 格式存储,即一个字符存放于两个字节;
  • Linux 系统中 UNICODE 默认采用 UTF-32 格式存储,即一个字符存放于四个字节;

VC 栈结构分析

分析 VC 生成汇编代码的栈帧结构,并比较 release 和 debug 版本的不同。

release 版本

汇编分析

  • 去掉编译优化选项
  • 查看汇编代码

    int fib(int x)
    {
    004017E0  push        ebp  
    004017E1  mov         ebp,esp 
    004017E3  sub         esp,10h 
    004017E6  push        esi  
        int a = 1;
    004017E7  mov         dword ptr [a],1 
        int b = 2;
    004017EE  mov         dword ptr [b],2 
        int c = 3;
    004017F5  mov         dword ptr [c],3 
        int d = 4;
    004017FC  mov         dword ptr [d],4 
    
        if (x == 2)
    00401803  cmp         dword ptr [x],2 
    00401807  jne         fib+33h (401813h) 
        {
          return 1 + 1 + a;
    00401809  mov         eax,dword ptr [a] 
    0040180C  add         eax,2 
    0040180F  jmp         fib+75h (401855h) 
    00401811  jmp         fib+75h (401855h) 
        }
        else if (x == 1)
    00401813  cmp         dword ptr [x],1 
    00401817  jne         fib+43h (401823h) 
        {
          return 1 + 0 + b;
    00401819  mov         eax,dword ptr [b] 
    0040181C  add         eax,1 
    0040181F  jmp         fib+75h (401855h) 
    00401821  jmp         fib+75h (401855h) 
        }
        else if (x == 0)
    00401823  cmp         dword ptr [x],0 
    00401827  jne         fib+50h (401830h) 
        {
          return 0 + c;
    00401829  mov         eax,dword ptr [c] 
    0040182C  jmp         fib+75h (401855h) 
        }
        else
    0040182E  jmp         fib+75h (401855h) 
        {
          return fib(x - 1) + fib(x - 2) + d;
    00401830  mov         eax,dword ptr [x] 
    00401833  sub         eax,1 
    00401836  push        eax  
    00401837  call        fib (4017E0h) 
    0040183C  add         esp,4 
    0040183F  mov         esi,eax 
    00401841  mov         ecx,dword ptr [x] 
    00401844  sub         ecx,2 
    00401847  push        ecx  
    00401848  call        fib (4017E0h) 
    0040184D  add         esp,4 
    00401850  add         esi,dword ptr [d] 
    00401853  add         eax,esi 
        }
    }
    00401855  pop         esi  
    00401856  mov         esp,ebp 
    00401858  pop         ebp  
    00401859  ret
    
  • 分析生成汇编
    • 栈变量的次序是调整过的,防止被 hacker 利用。查看下面的机器指令, E7,EE,F5,FC,显然地址不连续。

      004017E7  mov         dword ptr [a],1 
      004017EE  mov         dword ptr [b],2 
      004017F5  mov         dword ptr [c],3 
      004017FC  mov         dword ptr [d],4
      
    • 被调函数的处理
      • 将 ebp 压栈,保护上层栈基址。

        004017E0  push        ebp
        
      • ebp 指向原来 esp 的位置,指向新的栈基址。

        004017E1  mov         ebp,esp
        
      • esp 留出栈变量的空间,指向新的栈顶。这里留出 4 个 int 的空间 16 个字节:

        004017E3  sub         esp,10h
        
      • 将 esi 压栈,esi 在 fibonaci 函数中被临时使用,这里压栈是为了保护原始值。

        004017E6  push        esi
        
      • 将 esi 退栈

        00401855  pop         esi
        
      • 将 ebp 退栈,恢复上层调用的栈基址

        00401858  pop         ebp
        
      • 将 esp 指向 ebp 的位置,恢复上层调用用栈顶

        00401856  mov         esp,ebp
        
      • 将函数地址退栈,PC 寄存器跳回调用函数

        00401859  ret
        
    • 调用函数的处理
      • 将参数压栈

        00401836  push        eax
        
      • 将函数地址压栈

        00401837  call        fib (4017E0h)
        

栈帧结构

高地址
para1
para2
func addr
ebp
save reg1
save reg2
stack var1
stack var2
低地址

栈帧分析

  • 重点查找 ebp, func addr 两个线索
    • ebp 要连接成串,每个 ebp 指向下一个 ebp;
    • func addr 要在 dll 或 exe 的地址空间内。

debug 版本

汇编分析

  • 生成汇编代码

    int fib(int x)
    {
    004113B0  push        ebp  
    004113B1  mov         ebp,esp 
    004113B3  sub         esp,0F0h 
    004113B9  push        ebx  
    004113BA  push        esi  
    004113BB  push        edi  
    004113BC  lea         edi,[ebp-0F0h] 
    004113C2  mov         ecx,3Ch 
    004113C7  mov         eax,0CCCCCCCCh 
    004113CC  rep stos    dword ptr es:[edi] 
        int a = 1;
    004113CE  mov         dword ptr [a],1 
        int b = 2;
    004113D5  mov         dword ptr [b],2 
        int c = 3;
    004113DC  mov         dword ptr [c],3 
        int d = 4;
    004113E3  mov         dword ptr [d],4 
    
        if (x == 2)
    004113EA  cmp         dword ptr [x],2 
    004113EE  jne         fib+4Ah (4113FAh) 
        {
          return 1 + 1 + a;
    004113F0  mov         eax,dword ptr [a] 
    004113F3  add         eax,2 
    004113F6  jmp         fib+8Ch (41143Ch) 
    004113F8  jmp         fib+8Ch (41143Ch) 
        }
        else if (x == 1)
    004113FA  cmp         dword ptr [x],1 
    004113FE  jne         fib+5Ah (41140Ah) 
        {
          return 1 + 0 + b;
    00411400  mov         eax,dword ptr [b] 
    00411403  add         eax,1 
    00411406  jmp         fib+8Ch (41143Ch) 
    00411408  jmp         fib+8Ch (41143Ch) 
        }
        else if (x == 0)
    0041140A  cmp         dword ptr [x],0 
    0041140E  jne         fib+67h (411417h) 
        {
          return 0 + c;
    00411410  mov         eax,dword ptr [c] 
    00411413  jmp         fib+8Ch (41143Ch) 
        }
        else
    00411415  jmp         fib+8Ch (41143Ch) 
        {
          return fib(x - 1) + fib(x - 2) + d;
    00411417  mov         eax,dword ptr [x] 
    0041141A  sub         eax,1 
    0041141D  push        eax  
    0041141E  call        fib (411154h) 
    00411423  add         esp,4 
    00411426  mov         esi,eax 
    00411428  mov         ecx,dword ptr [x] 
    0041142B  sub         ecx,2 
    0041142E  push        ecx  
    0041142F  call        fib (411154h) 
    00411434  add         esp,4 
    00411437  add         esi,dword ptr [d] 
    0041143A  add         eax,esi 
        }
    }
    0041143C  pop         edi  
    0041143D  pop         esi  
    0041143E  pop         ebx  
    0041143F  add         esp,0F0h 
    00411445  cmp         ebp,esp 
    00411447  call        @ILT+320(__RTC_CheckEsp) (411145h) 
    0041144C  mov         esp,ebp 
    0041144E  pop         ebp  
    0041144F  ret
    
  • 栈变量空间至少保留 0xF0 = 240 字节的空间

    004113B3  sub         esp,0F0h
    
  • 栈变量空间被初始化成 0xCC

    004113BC  lea         edi,[ebp-0F0h] 
    004113C2  mov         ecx,3Ch 
    004113C7  mov         eax,0CCCCCCCCh 
    004113CC  rep stos    dword ptr es:[edi]
    
  • 退栈时会作 ebp 检查,防止栈被破坏

    0041143F  add         esp,0F0h 
    00411445  cmp         ebp,esp 
    00411447  call        @ILT+320(__RTC_CheckEsp) (411145h)
    

栈帧结构

  • 栈变量的分配留有很大裕量,为每个 int 分配了 4*4=16 个字节空间。