汇编常用的寄存器有:
data register:EAX,EBX,ECX,EDX
segment register: CS, DS, EX, FS, GS, SS
index register: ESI, EDI(表示源和目的
pointer register: EIP, ESP, EBP
EIP 为指令指针, ESP 为堆栈指针,EBP为基址指针寄存器,用来标识栈中某一固定位置,当调用子过程中有参数时常用EBP来容易分出参数的位置。对于跳转常用的几个指令有:call,jmp, ret.
jmp a = move a EIP 将目的地址放到EIP 中然后执行
call = push EIP + jmp 即先将下一条指令压栈,然后跳转
ret = pop EIP 即将要返回的地址放到EIP中
举个具体例子(example.c):
int add(int a, int b){
return a+b;
}
int main(){
add(7,9);
}
#gcc -o a.out example.c
#objdump -d a.out
08048394 <add>:
8048394: 55 push %ebp
8048395: 89 e5 mov %esp,%ebp
8048397: 8b 45 0c mov 0xc(%ebp),%eax
804839a: 03 45 08 add 0x8(%ebp),%eax
804839d: 5d pop %ebp
804839e: c3 ret
0804839f <main>:
804839f: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483a3: 83 e4 f0 and $0xfffffff0,%esp
80483a6: ff 71 fc pushl -0x4(%ecx)
80483a9: 55 push %ebp
80483aa: 89 e5 mov %esp,%ebp
80483ac: 51 push %ecx
80483ad: 83 ec 08 sub $0x8,%esp
80483b0: c7 44 24 04 09 00 00 movl $0x9,0x4(%esp)
80483b7: 00
80483b8: c7 04 24 07 00 00 00 movl $0x7,(%esp)
80483bf: e8 d0 ff ff ff call 8048394 <add>
80483c4: 83 c4 08 add $0x8,%esp
80483c7: 59 pop %ecx
80483c8: 5d pop %ebp
80483c9: 8d 61 fc lea -0x4(%ecx),%esp
80483cc: c3 ret
80483cd: 90 nop
80483ce: 90 nop
80483cf: 90 nop
对于子过程add, 在栈中的位置如下
高-----------------低
| 9 | 7 | 80483c7 | %ebp |
——————————————————
过程调用进入子过程时一般都有下面两条指令:
push %ebp,
mov %esp, %ebp
为什么使用ebp呢 这是因为ESP的内容很容易改变,而使用ebp可以作为固定参考点,来获取参数