C反汇编实例

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C反汇编实例(2011-07-13 13:04:41)转载▼

标签:c 反汇编it 分类:驱动与内核

该例的要求是求两个3x3矩阵的乘积,其C源代码如下:

intmyfunction(int a[3][3], int b[3][3], int c[3][3])

{

inti, j;

for (i = 0; i< 3; ++i)

{

for (j = 0; j < 3; ++j)

c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];

}

return 0;

}

相当简单吧?呵呵,那么希望你看过了下面的反汇编代码后,还能这样乐观。

如下的反汇编代码,据原书作者,在VC2003,debug模式下得到,同时我在VC2008PRO下得到汇编代码完全相同,可以通用,但此处引用原书中的代码。

00411A3E movdwordptr [i],0

00411A45 jmp myfunction+30h (411A50h)

00411A47 moveax,dwordptr [i]

00411A4A add eax,1

00411A4D movdwordptr [i],eax

00411A50 cmpdwordptr [i],3

00411A54 jge myfunction+0AEh (411ACEh)

00411A56 movdwordptr [j],0

00411A5D jmp myfunction+48h (411A68h)

00411A5F moveax,dwordptr [j]

00411A62 add eax,1

00411A65 movdwordptr [j],eax

00411A68 cmpdwordptr [j],3

00411A6C jge myfunction+0A9h (411AC9h)

00411A6E moveax,dwordptr [i]

00411A71 imul eax,eax,0Ch

00411A74 movecx,dwordptr [a]

00411A77 movedx,dwordptr [j]

00411A7A movesi,dwordptr [b]

00411A7D moveax,dwordptr [ecx+eax]

00411A80 imuleax,dwordptr [esi+edx*4]

00411A84 movecx,dwordptr [i]

00411A87 imul ecx,ecx,0Ch

00411A8A movedx,dwordptr [a]

00411A8D movesi,dwordptr [j]

00411A90 movedi,dwordptr [b]

00411A93 movecx,dwordptr [edx+ecx+4]

00411A97 imulecx,dwordptr [edi+esi*4+0Ch]

00411A9C add eax,ecx

00411A9E movedx,dwordptr [i]

00411AA1 imul edx,edx,0Ch

00411AA4 movecx,dwordptr [a]

00411AA7 movesi,dwordptr [j]

00411AAA movedi,dwordptr [b]

00411AAD movedx,dwordptr [ecx+edx+8]

00411AB1 imuledx,dwordptr [edi+esi*4+18h]

00411AB6 add eax,edx

00411AB8 movecx,dwordptr [i]

00411ABB imul ecx,ecx,0Ch

00411ABE add ecx,dwordptr [c]

00411AC1 movedx,dwordptr [j]

00411AC4 movdwordptr [ecx+edx*4],eax

00411AC7 jmp myfunction+3Fh (411A5Fh)

00411AC9 jmp myfunction+27h (411A47h)

首先先简单提一下,C语言中多维数组的存储方式,其存储的规则是,列优先于行,也就是:若有a[3][3],则顺序是a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]。其实所谓的多维数组这样高级语言才有的数据结构,在底层实现中,无非就是一片连续分配的一维内存空间而已,大家千万别看得太过神秘了。

接着要提一下C语言中指针在汇编实现时的情况。汇编可以说把高级语言中几乎所有现象的本质都暴露了出来。现观察一下以下情况:对于int a[3][3]定义的多维数组变量a,a本身表示的是该矩阵首行的地址,而a[0](或者*a)是首行首列元素的地址,两者是不同的指针类型,然而很容易知道在地址数值上两者是相等的,我们引申开来,比如我们要访问a[m][n],我们还可以写作*(*(a + m) + n),但由上段所述,实际上就是把a所含的地址再往后移m * 3 * 4(int占4个字节) + n * 4个字节(此注:a + m不是a所在处后移m个字节!可以把a理解为int[3]这种类型的指针,所以加了m,其实是加了12* m个bytes)就是所要访问的内存,换句话说任何多维数组总可以用一个一维普通指针(比如使用指针类型强制转换)完全访问到,尽管在高级语言中这样的做法是非常不明智且危险的。但汇编却正是这么做的!比如我们有C语句:a[i][j] = 2;,用C还可以写作*(*(a + i) + j) = 2,而用汇编则可能是这样,moveax, dwordptr [i] ; 把i的值读入eax

imuleax, eax, 0Ch ; 把eax乘以12,因为一行有三个int,3 * 4 = 12

lea ecx, a[eax] ; 相当于将a所含的地址与eax相加后存入ecx

movedx, dwordptr [j] ; 把j的值读入edx

movdwordptr [ecx + edx * 4], 2 ; ecx + edx就是a[i][j]的地址

我们尝试省略寄存器的中间步骤、并逐式代入的话,就直接可以推出这个式子:movdwordptr [a + i * 12 + j * 4], 2 ;这个式子和上述的完全一致。

最后提到的就是C中for语句的汇编实现。

for (init; condition; expr)

loop-body

大家都应当很清楚,执行的顺序是:先init初始化循环变量,接着判断condition,若满足则执行循环体(loop-body),再执行expr,判断条件是否满足,满足则执行loop-body……汇编代码是非常机械地对应着上述过程,例:

相关文档
最新文档