@iar
2016-08-13T02:15:25.000000Z
字数 3208
阅读 88
Linux
Note
OS
Heng Zhang + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
Command+src=>target
movl %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, %esp
movl %eax, (%esp)
popl %eax \\ 等价如下
movl (%esp), %eax
addl $4, %esp
call 0x12345 \\ 等价如下
pushl %eip
movl $0x12345, %eip
ret \\ 等价如下
popl %eip
enter \\ 等价如下
pushl %ebp
movl %esp, %ebp
leave \\ 等价如下
movl %ebp, %esp
popl %ebp
int g(int x)
{
return x+42;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(4)+17;
}
.
开头的部分都删了)
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $42, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $4, (%esp)
call f
addl $17, %eax
leave
ret
0x80483e2 <frame_dummy+34> jmp 0x8048360 <register_tm_clones>
0x80483e7 <frame_dummy+39> nop
0x80483e8 <frame_dummy+40> jmp 0x8048360 <register_tm_clones>
0x80483ed <g> push %ebp
0x80483ee <g+1> mov %esp,%ebp
0x80483f0 <g+3> mov 0x8(%ebp),%eax
0x80483f3 <g+6> add $0x2a,%eax
0x80483f6 <g+9> pop %ebp
0x80483f7 <g+10> ret
0x80483f8 <f> push %ebp
0x80483f9 <f+1> mov %esp,%ebp
0x80483fb <f+3> sub $0x4,%esp
0x80483fe <f+6> mov 0x8(%ebp),%eax
0x8048401 <f+9> mov %eax,(%esp)
0x8048404 <f+12> call 0x80483ed <g>
0x8048409 <f+17> leave
0x804840a <f+18> ret
0x804840b <main> push %ebp
0x804840c <main+1> mov %esp,%ebp
0x804840e <main+3> sub $0x4,%esp
0x8048411 <main+6> movl $0x4,(%esp)
0x8048418 <main+13> call 0x80483f8 <f>
0x804841d <main+18> add $0x11,%eax
0x8048420 <main+21> leave
0x8048421 <main+22> ret
0x8048422 xchg %ax,%ax
0x8048424 xchg %ax,%ax
0x8048426 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, 保证了对应.