计算机是如何工作的_试验一
汇编一个简单的程序
初始程序如下:
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 1;
}
之后,在终端中输入命令:gcc -S -o main.s main.c -m32
-S目的为输出汇编文件,-o后跟输出目标文件名称,-m32用来产生32位汇编代码。
打开main.s后为汇编代码,如图:
汇编文件中有一些“.”打头的字符串是编译器在链接阶段需要的辅助信息或在预编译阶段将头文件展开的信息,可通过命令:g/.s*/d将其删掉再进行汇编代码分析,删除后如图:
分析汇编指令执行过程
如上图,简化后的汇编指令很容易看出只剩g,f,main三个函数,下面对每行汇编指令做简要分析:
g:
pushl %ebp //将ebp的值压栈,指向4的位置
movl %esp, %ebp //ebp也指向esp的位置
movl 8(%ebp), %eax //变址寻址ebp 加8,赋值给eax
addl $3, %eax //将立即数3加到eax中,变为11
popl %ebp //将现在ebp的值出栈,指向4的位置,esp指向6
ret //pop %eip eip指向5的位置
f:
pushl %ebp //将ebp的值压栈,esp向下移动一个存储单位
movl %esp, %ebp //把esp的值赋给ebp(标号)
subl $4, %esp //esp减4,指向5的位置
movl 8(%ebp), %eax //ebp变址寻址8,赋给eax,eax等于8
movl %eax, (%esp) //将eax放到esp的位置
call g //pushl eip;movl g %eip 此时eip指向g
leave //movl %ebp %esp;popl %ebp
ret //pop %eip
main:
pushl %ebp //把EBP寄存器的值压栈,先把ESP寄存器指向下一栈空间
movl %esp, %ebp //将EBP寄存器变为ESP寄存器的值,指向标号1的位置
subl $4, %esp //将ESP向下移动一个栈空间
movl $8, (%esp) //将立即数8放入ESP指向的当前位置,标号2
call f //pushl eip;movl f %eip 此时eip指向f
addl $1, %eax //将立即数1加到eax中
leave //movl %ebp %esp;popl %ebp
ret //pop %eip
如下图: