汇编与对应C++伪码(1)

对于《C++反汇编与逆向分析技术揭秘》第一章~第四章学习过程中的一些汇编代码及对应的c++代码的积累。

一、第一章

浮点数相关

(1)

(2)浮点数作为返回值

(3)类型转换函数_ftol(将float型转换为int型)的实现

二、第二章

指针

(1)各类型指针访问同一地址

(2)各类型指针的寻址方式

常量

四、第四章

算术运算与赋值
1.各种算术运算的工作形式

####### 代码片段1

####### 代码片段2

其优化过程如下——

####### 减法运算示例——Debug版


####### 各类型乘法转换——Debug版


####### 乘数不等于2\4\8的组合运算

####### 各类型乘法转换——Releas版


在这里补充一个知识点,关于汇编指令lea

  • 如果lea指令的第二个操作数是寄存器必须要加[],不然会报错,此时lea就是取[寄存器]的值。如:mov eax,2; lea ebx,[eax];执行后ebx=2。
  • 如果lea指令的第二个操作数是变量,加不加[]都是一样的效果,都是取变量的地址,相当于指针。如:num dword 2; lea ebx,num; lea eax,[num]; eax为num的地址,如eax=4206598,随程序不同不同,这时ebx==eax。

有的作者(以及编译器)会利用lea指令支持的寻址模式(即第二个操作数是寄存器的情况)来计算一些例如一个数乘2/4/8并且加另一个数一类的运算,所以如果你感觉计算的东西不太像个真正的内存地址,它有可能真的不是。例如——

lea edx, ds:5[esi*4]        //此句代码等同于lea edx, [esi*4+5],都是混合运算;
                            //此时esi中存的是一个具体的变量值;
                            //执行之后edx=(esi中的值*4+5);

补充参考资料——

(1)汇编语言中mov和lea的区别有哪些?;
(2)汇编中中括号作用以及lea和mov指令的区别;

####### 各类型除法转换——Debug版


(1)该代码中只对除数为2的幂的情况进行了优化处理,其理论推导如下图——

代码中0040B80C的cdq是符号扩展到高位edx,如果eax的最高位(符号位)为1,那么edx的值为0xFFFFFFFF,也就是-1,否则为0。0040B80D地址处的sub eax,edx指令执行的操作是将eax减去高位edx,实际上就是被除数为负数的情况下由于除数为正数(+2的幂),故除法的商为负数。移位运算等价于向下取整,C语言的除法是向零取整,因此需要对商为负的情况做加1调整(见上图推导结论),减去-1等同于加1。eax不为负则减0,等于没处理。最后sar右移完成除法。这样的设计可以避免分支结构的产生。

代码中0040B854的cdq是符号扩展到高位edx,如果eax的最高位(符号位)为1,就是说被除数eax里面保留了负数值,那么edx的值为0xFFFFFFFE,也就是-1,否则为0。在以上代码中,0040B855处对edx做位与运算,当被除数为负数时,edx的值为7,否则为0。在0040B858处的 add eax,edx就是被除数为负数时加上8-1,不为负则加0,等于没处理。最后sar右移完成除法。

####### 各类型除法转换——Release版

(2)该代码中对除数不为2的幂的情况做了优化,其理论推导1如下图——

在解释其含义前,我们先来看看两个相关的小练习——

  • 练习1

在地址text:00401004处,我们看到了 mov eax,38E38E3h,此后做了乘法和移位操作,最后直接使用edx显示。在乘法指令中,由于edx存放乘积数据的高4字节,因此直接使用edx就等价于乘积右移了32位,再算上text:0040100B sar edx,1,那就一共移动了33位

在地址text:0040100D处,eax得到了edx的值,然后对eax右移了1Fh位,对应10进制也就是右移了31位,然后有个很奇怪的加法。其实这里移位的目的是得到有符号数的符号位,如果结果是正数, add edx,eax就是加0,等于什么都没干;如果结果是负数,由于其后面的代码直接使用edx作为计算结果,需要对除法的商调整加1。

该汇编代码反推出优化前的高级代码为——

printf("%d", argc/9);

由此引申出的通用模式1总结如下——

  • 练习2

详细的推导参见教程,这里只给出由此引申出的通用模式2总结如下——

回到两个练习之前的代码部分(对红框中加法指令的详细解释见教材)——

由此引申出的通用模式3总结如下——

(3)除数为负的2的幂——理解同上除数为正的2的幂。

(4)除数为负的非2的幂——注意如何区分除数为负和除数为正的情况。

  • 情况1

由此引申出的通用模式4总结如下——

  • 情况2

由此引申出的通用模式5总结如下——

####### 取模运算

####### 取绝对值


2.自增和自减


关系运算与逻辑运算
1.表达式短路

(1)使用逻辑与完成表达式短路实现跳过递归调用


(2)使用逻辑或完成表达式短路实现跳过递归调用


2.条件表达式

(1)

(2)

由此引申出的通用模式6总结如下——

(3)


由此引申出的通用模式7总结如下——

(4)


位运算
1.有符号数的运算——Debug版


2.无符号数的位移——Debug版