编译程序的功能就是把用高级语言编写的程序
翻译成与之等价的目标程序。现在汇编语言已经能够被机器所理解,而高级语言大多数必须要被翻译成汇编语言才能被程序理解,所以知道高级语言是怎么被翻译成汇编语言对程序员来说很有必要。本篇文章用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程序,我觉得这段汇编程序更容易理解了。