程序的机器级表示

编译程序的功能就是把用高级语言编写的程序翻译成与之等价的目标程序。现在汇编语言已经能够被机器所理解,而高级语言大多数必须要被翻译成汇编语言才能被程序理解,所以知道高级语言是怎么被翻译成汇编语言对程序员来说很有必要。本篇文章用C语言与汇编语言对比,简单的介绍下高级语言到汇编语言的过程。 先从C开始吧: int demo(){ int x = 10; int y = 20; int sum = add(&x, &y); PRintf(“the sum is %d\n”,sum); return sum; } int add(int *xp, int *yp){ int x = *xp; int y = *yp; return x+y; } 这段简短的C程序很简单,在这里不做解释。现在来看看与这段程序的等价的汇编表示: demo: 1 pushl %ebp 2 movl %esp %ebp 3 subl %24 esp 4 movl $10 -4(%ebp) 5 movl $20 -8(%ebp) 6 leal -8(%ebp) %eax 7 movl %eax 4(%esp) 8 leal -4(%ebp) %eax 9 movl %eax esp 10 call add add: 1 pushl %ebp 2 movl %esp %ebp 3 pushl %ebx 4 movl 8(%ebp) %edx 5 movl 12(%ebp) %ecx 6 movl (%edx) %ebx 7 movl (%ecx) %eax 8 add %ebx %eax 9 popl %ebx 10 popl %ebp 11 ret 这段程序实现的功能与上面那段C程序一样,但要看懂这段汇编,相信对于大多数初学者来说是有一定的难度的。为了读懂这段汇编程序,我们必须要有一定的知识储备: MOVL $0x3051 ,%EAX;把0x3051这个值放到 EAX寄存器, 4个字节 MOVL %EAX, -12(%EBP);把EAX的值,存放到EBP指的地址减去12个字节处 LEAL -12(%EBP) %EAX;把 %EBP减去12得到的地址,放到EAX寄存器当中 PUSHL %EBP;把寄存器EBP的值压栈 POPL %EBP;把栈顶的值弹出, 存放到EBP寄存器中 SUBL %4 %ESP;把ESP寄存器的值减去4 好了,有了这些储备知识,再回过头来看这段汇编就容易懂得多了。这里必须要再提一下的是esp与ebp。esp是堆栈指针,ebp是基址指针,函数从硬盘读入内存,在进程的虚拟地址空间中会有一个个函数的栈帧,ebp指向函数的开始,esp指向函数的栈顶,在函数执行之前,进程管理会为函数的执行留够执行的空间。 好了,现在汇编函数开始执行了: 1 pushl %ebp 2 movl %esp %ebp 把寄存器ebp的值压栈,然后把esp的值存放到ebp指向的地址中去,假设现在esp与ebp的值都是800; 3 subl %24 esp 把esp的值减去24,则现在esp的地址是776,这样做的目的是为这个函数划分执行时所要的地址空间。 4 movl $10 -4(%ebp) 5 movl $20 -8(%ebp) 在地址为796(800-4)的空间存入值为10的数据,在地址为792(800-8)的空间存入值为20的数据; 6 leal -8(%ebp) %eax 7 movl %eax 4(%esp) 8 leal -4(%ebp) %eax 9 movl %eax esp 把ebp减去8的地址存(792)放到eax寄存器中去,然后把eax的值存放到esp+4(780)的地方去。这样做了之后的结果就是:地址为780的空间中存入了792,注意,792是值20的地址;同理地址为776的地方存入了796; 10 call add 调用add函数,这里会留下一个返回地址; 1 pushl %ebp 2 movl %esp %ebp 3 pushl %ebx 接着上面的函数来,把ebp压入栈,然后把esp的值存入ebp指向的地址,这时768的地址空间中存入了800;764的地址空间中存入了ebx的值。其余语句执行情况与demo类似,最后执行到: 8 add %ebx %eax 前面已经把ebp+8(也就是地址776)中的值存放到了edx寄存器中,把ebp+12(也就是地址780)的值存放到了ecx寄存器中,然后取地址,分别把10和20分别存放到了寄存器ebx和eax中,然后执行加法运算求得结果。 9 popl %ebx 10 popl %ebp 把返回地址弹出存入到了ebx中,把上一个函数的开始地址弹出存放到了ebp中,执行到这里,又到了demo的函数帧,然后会把运算的结果打印出来。至此,这个函数就执行完了。怎么样,对比着C程序,我觉得这段汇编程序更容易理解了。