【vc++精品源码栏目提醒】:网学会员鉴于大家对vc++精品源码十分关注,论文会员在此为大家搜集整理了“【精品】C反汇编实例 - 其它资料”一文,供大家参考学习
C 反汇编实例 呵,好久没写 CSDN 文章了,来凑个热闹。
最近我阅读了楚狂人wowocock 写的《天书夜读》试读本,对 C 反汇编感触颇深,书中有一例算法反汇编,其对汇编的阅读确实富有挑战,而该书中也未详解,在此,我谨将此例详细分析如下,帮助大家更好理解 C 反汇编代码,若有任何错误,请大家批评指正! 该例的要求是求两个 3x3 矩阵的乘积,其 C 源代码如下:int myfunctionint a33 int b33 int c33 int i j for i 0 i 3 i for j 0 j 3 j cij ai0 b0j ai1 b1j ai2 b2j return 0相当简单吧?呵呵,那么希望你看过了下面的反汇编代码后,还能这样乐观。
如下的反汇编代码,据原书作者,在 VC2003,debug 模式下得到,同时我在 VC2008PRO下得到汇编代码完全相同,可以通用,但此处引用原书中的代码。
00411A3E mov dword ptr i000411A45 jmp myfunction30h 411A50h00411A47 mov eaxdword ptr i00411A4A add eax100411A4D mov dword ptr ieax00411A50 cmp dword ptr i300411A54 jge myfunction0AEh 411ACEh00411A56 mov dword ptr j000411A5D jmp myfunction48h 411A68h00411A5F mov eaxdword ptr j00411A62 add eax100411A65 mov dword ptr jeax00411A68 cmp dword ptr j300411A6C jge myfunction0A9h 411AC9h00411A6E mov eaxdword ptr i00411A71 imul eaxeax0Ch00411A74 mov ecxdword ptr a00411A77 mov edxdword ptr j00411A7A mov esidword ptr b00411A7D mov eaxdword ptr ecxeax00411A80 imul eaxdword ptr esiedx400411A84 mov ecxdword ptr i00411A87 imul ecxecx0Ch00411A8A mov edxdword ptr a00411A8D mov esidword ptr j00411A90 mov edidword ptr b00411A93 mov ecxdword ptr edxecx400411A97 imul ecxdword ptr ediesi40Ch00411A9C add eaxecx00411A9E mov edxdword ptr i00411AA1 imul edxedx0Ch00411AA4 mov ecxdword ptr a00411AA7 mov esidword ptr j00411AAA mov edidword ptr b00411AAD mov edxdword ptr ecxedx800411AB1 imul edxdword ptr ediesi418h00411AB6 add eaxedx00411AB8 mov ecxdword ptr i00411ABB imul ecxecx0Ch00411ABE add ecxdword ptr c00411AC1 mov edxdword ptr j00411AC4 mov dword ptr ecxedx4eax00411AC7 jmp myfunction3Fh 411A5Fh00411AC9 jmp myfunction27h 411A47h晕了?呵呵,如果你第一遍看就可以完全读通,那我只好对您 Orz 了= =,希望你们这些天才别来砸我场子啊_ 首先先简单提一下,C 语言中多维数组的存储方式。
其存储的规则是,列优先于行,也就是:若有 a33,则顺序是 a00 a01 a02 a10 a11 a12 a20 a21a22。
其实所谓的多维数组这样高级语言才有的数据结构,在底层实现中,无非就是一片连续分配的一维内存空间而已,大家千万别看得太过神秘了。
接着要提一下 C 语言中指针在汇编实现时的情况。
汇编可以说把高级语言中几乎所有现象的本质都暴露了出来。
现观察一下以下情况:对于 int a33定义的多维数组变量 a,a本身表示的是该矩阵首行的地址,而 a0(或者a)是首行首列元素的地址,两者是不同的指针类型,然而很容易知道在地址数值上两者是相等的,我们引申开来,比如我们要访问amn,我们还可以写作a m n,但由上段所述,实际上就是把 a 所含的地址再往后移 m 3 4int 占 4 个字节 n 4 个字节(此注:a m 不是 a 所在处后移 m 个字节!可以把 a 理解为 int3这种类型的指针,所以加了 m,其实是加了 12 m 个 bytes)就是所要访问的内存, 换句话说任何多维数组总可以用一个一维普通指针 (比如使用指针类型强制转换)完全访问到,尽管在高级语言中这样的做法是非常不明智且危险的。
但汇编却正是这么做的!比如我们有 C 语句:aij 2,用 C 还可以写作a i j 2,而用汇编则可能是这样,mov eax dword ptr i 把 i 的值读入 eaximul eax eax 0Ch 把 eax 乘以 12,因为一行有三个 int,3 4 12lea ecx aeax 相当于将 a 所含的地址与 eax 相加后存入 ecxmov edx dword ptr j 把 j 的值读入 edxmov dword ptr ecx edx 4 2 ecx edx 就是 aij的地址 我们尝试省略寄存器的中间步骤、并逐式代入的话,就直接可以推出这个式子:mov dword ptr a i 12 j 4 2 ;这个式子和上述的完全一致。
最后提到的就是 C 中 for 语句的汇编实现。
for init condition expr loop-body大家都应当很清楚,执行的顺序是:先 init 初始化循环变量,接着判断 condition,若满足则执行循环体loop-body,再执行 expr,判断条件是否满足,满足则执行 loop-body……汇编代码是非常机械地对应着上述过程,例:for i 0 i 5 iloop-body则相应汇编代码: 初始化代码mov dword ptr i 0jmp 无条件跳转到所在代码,这里不列出具体的代码地址了 这段就是 expr,类似用一个中间变量(只不过这里是寄存器)的办法来给 i 加一mov eax dword ptr iadd eax 1mov dword ptr i eax 这段则是判断条件,condition cmp dword ptr i 5 比较 i 和 5jge jge 表示 jump to when i is greater than or equal to 5,大于等于 5 跳转,指向的是 for 循环后面接着的代码,也就是跳出循环 以下段省略,是循环体 loop-body…jmp 无条件跳转到 expr,并进而判断条件 以下是 for 循环以外的代码… 那么有了上述三方面的基础,我们就可以来逐一解读那段“传奇”的汇编代码了。
初始化 i00411A3E mov dword ptr i0跳转至条件判断00411A45 jmp myfunction30h 411A50h循环表达式,对 i 每轮加 100411A47 mov eaxdword ptr i00411A4A add eax100411A4D mov dword ptr ieax条件判断,若不满足 i 3,则跳出循环00411A50 cmp dword ptr i300411A54 jge myfunction0AEh 411ACEh i 的循环体 ,可以对比这里比较特殊,传说中的“嵌套循环”最前面的 C 代码看一下,其实是一样的初始化 j00411A56 mov dword ptr j0跳至 j 循环的条件判断00411A5D jmp myfunction48h 411A68h每轮对 j 加 100411A5F mov eaxdword ptr j00411A62 add eax100411A65 mov dword ptr jeaxj 循环的条件判断00411A68 cmp dword ptr j300411A6C jge myfunction0A9h 411AC9h j 的循环体… 这里省略的是数组赋值的过程代码,会在稍后分析 j 的循环体结束跳到 j 的 expr00411AC7 jmp myfunction3Fh 411A5Fh i 的循环体结束跳至 i 的 expr00411AC9 jmp myfunction27h 411A47h 以下我们再详细分析下上面挖下来的数组赋值的代码。
为了方便起见,再把 C 语句贴如下:cij ai0 b0j ai1 b1j ai2 b2j 还记得前面所说的汇编访问二维数组的方式么?忘记的话,再回过头去看一下哈 第i行,每行3个占4字节的int类型,所以乘以i×12(0Ch),表示行偏移00411A6E mov eaxdword ptr i00411A71 imul eaxeax0Ch 往寄存器送入一些变量00411A74 mov ecxdword ptr a00411A77 mov edxdword ptr j00411A7A mov esidword ptr b00411A7D mov eaxdword ptr ecxeax ecx 已经含有 a 数组的起始地址,这句相当于往 eax 存入基址+i 行偏移这个地址开始的 int 类 型值,也就是 ai000411A80 imul eaxdword ptr esiedx4 这句比较好理解,esi 是 b 数组起始地址 edx 4 表示列偏移相当于 eax b0j, 也就是 e
上一篇:
【精品】PCL6045BL与PCL6045B以太网评估板ETH6045D介绍
下一篇:
白色姜花,略微开了