标签:enter ref turn 自动 tar 左移 实验 pre 分享
本文章为《Linux内核分析》实验报告
梁永锐
原创作品转载请注明出处 http://www.cnblogs.com/liangyongrui/p/6392035.html
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
-----
以下为要分析的c代码
int g(int x) { return x + 36; } int f(int x) { return g(x) * 4; } int main(void) { return f(81) + 12; }
gcc –S –o main.s main.c -m32
编译成32位汇编后(去了点开头的行
g: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl $36, %eax popl %ebp ret f: pushl %ebp movl %esp, %ebp pushl 8(%ebp) call g addl $4, %esp sall $2, %eax leave ret main: pushl %ebp movl %esp, %ebp pushl $81 call f addl $4, %esp addl $12, %eax leave ret
一.实验截图:
二. 汇编代码的工作过程中堆栈的变化
从main开始
pushl %ebp
movl %esp, %ebp
也就是enter指令(不知道为什么这里并没有把他写成enter而是分开写了)
这两条指令执行后我们假设,ebp,esp均为100(以下内容用ebp=100, esp=100这种方法表示)
pushl $81
ebp=100, esp = 96,[96]=81([96]=81, 表示位置96的地方存了81这个数, 以下均用这种方法表示)
call f
ebp = 100, esp = 92, [92]= 22(这里用行号做eip)
跳到了f
pushl %ebp
ebp = 100, esp = 88, [88]=100
movl %esp, %ebp
ebp = 88, esp = 88
pushl 8(%ebp)
ebp = 88, esp = 84, [84] = 81
call g
ebp = 88, esp = 80, [80] = 13
然后调到了g函数
pushl %ebp
ebp = 88, esp = 76, [76] = 88
movl %esp, %ebp
ebp = 76, esp = 76
movl 8(%ebp), %eax
把传入的参数放在eax中, eax = 81
addl $36, %eax
eax = 81 + 36 = 117
popl %ebp
ebp = 88, esp = 80
ret
ebp = 88, esp = 84, eip = 13
此时就跳到13行了
addl $4, %esp
弹出传入的参数,不赋值
ebp = 88, esp = 88
sall $2, %eax
编译器很智能,乘4,自动变成了左移两位, eax = 117 << 2 = 468
leave
leave就是
movl %ebp, %esp : ebp = 88, esp = 88
popl %ebp : ebp = 100, esp = 92
ret
ebp = 100, esp = 94, eip = 22
跳到第22行
addl $4, %esp
弹出参数
esp = 96
addl $12, %eax
eax = 468 + 12 = 480
leave
ret
回到main函数之前的堆栈和eip
三.计算机是如何工作的
简单的说,计算机就是按照ip一条条的执行指令,执行的时候需要一些寄存器做辅助,ip有时候也会跳。
标签:enter ref turn 自动 tar 左移 实验 pre 分享
原文地址:http://www.cnblogs.com/liangyongrui/p/6392035.html