@iar
2016-08-12T18:15:25.000000Z
字数 3208
阅读 119
Linux Note OS
Heng Zhang + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
Command+src=>targetmovl %eax, %edx (register mode)movl %0x417, %edx (immediate)movl 0x417, %edx (direct)movl (%ebx), %edx (indirect)movl 4(%ebx), %edx (displaced)% : 表示那个寄存器$ : 立即数(): 间接寻址
pushl %eax \\ 等价如下subl $4, %espmovl %eax, (%esp)popl %eax \\ 等价如下movl (%esp), %eaxaddl $4, %espcall 0x12345 \\ 等价如下pushl %eipmovl $0x12345, %eipret \\ 等价如下popl %eip
enter \\ 等价如下pushl %ebpmovl %esp, %ebpleave \\ 等价如下movl %ebp, %esppopl %ebp
int g(int x){return x+42;}int f(int x){return g(x);}int main(void){return f(4)+17;}

.开头的部分都删了)
g:pushl %ebpmovl %esp, %ebpmovl 8(%ebp), %eaxaddl $42, %eaxpopl %ebpretf:pushl %ebpmovl %esp, %ebpsubl $4, %espmovl 8(%ebp), %eaxmovl %eax, (%esp)call gleaveretmain:pushl %ebpmovl %esp, %ebpsubl $4, %espmovl $4, (%esp)call faddl $17, %eaxleaveret


0x80483e2 <frame_dummy+34> jmp 0x8048360 <register_tm_clones>0x80483e7 <frame_dummy+39> nop0x80483e8 <frame_dummy+40> jmp 0x8048360 <register_tm_clones>0x80483ed <g> push %ebp0x80483ee <g+1> mov %esp,%ebp0x80483f0 <g+3> mov 0x8(%ebp),%eax0x80483f3 <g+6> add $0x2a,%eax0x80483f6 <g+9> pop %ebp0x80483f7 <g+10> ret0x80483f8 <f> push %ebp0x80483f9 <f+1> mov %esp,%ebp0x80483fb <f+3> sub $0x4,%esp0x80483fe <f+6> mov 0x8(%ebp),%eax0x8048401 <f+9> mov %eax,(%esp)0x8048404 <f+12> call 0x80483ed <g>0x8048409 <f+17> leave0x804840a <f+18> ret0x804840b <main> push %ebp0x804840c <main+1> mov %esp,%ebp0x804840e <main+3> sub $0x4,%esp0x8048411 <main+6> movl $0x4,(%esp)0x8048418 <main+13> call 0x80483f8 <f>0x804841d <main+18> add $0x11,%eax0x8048420 <main+21> leave0x8048421 <main+22> ret0x8048422 xchg %ax,%ax0x8048424 xchg %ax,%ax0x8048426 xchg %ax,%ax
- 按照老师的Stack的画法: 横线是地址, 横线上的空格表示该地址所存储的值. 空格中, 使用
('值').- 为了方便, 地址的增加为1, 实际上32位机是增加4 byte, 不过为了方便演示学习. 这里的单位是1byte.
- C 文件从main函数开始, 此时ebp, esp指向loc: 0. eip永远指向当前命令的下一条指令. 这样CPU才会知道下一步跑什么.
- main的最后: ret, 执行的main函数之前的eip. 这里由操作系统管理.
- eax默认作为函数的返回值return给上一级函数.

pushl %ebp => esp-=4, movl ebp,esp: 
movl %esp, %ebp: 
subl $4, %esp: 
movl $4, (%esp): 
call f => pushl eip, movl f, eip: 
pushl %ebp: 
movl %esp, %ebp: 
subl $4, %esp: 
movl 8(%ebp), %eax: 
movl %eax, (%esp): 
call g: 
pushl %ebp: 
movl %esp, %ebp: 
addl $42, %eax: 
popl %ebp: 
ret: 
leave. 注意这里我分了2步把leave画出来: 先是movl, 然后pop.

ret. 
addl $17, %eax. 
leave. 还是一样, 把leave分解为mov和pop:

ret. 此时eip回到main之前的函数指定的eip处.popl %reg的时候就能正好拿到这个%reg, 事实上是pushl, 以及subl/addl, 保证了对应.