有两种汇编格式:Intel汇编和AT&T汇编,前者常用于Windows,后者常用于Unix,是GNU汇编器的缺省格式,本文介绍后者(AT&T汇编格式)。
1,常用指令及解释
movl %eax, %edx --- 数据传递,%eax地址传递给%edx
pushl %eax --- 入栈,分两步:subl $4, %esp(栈向低地址方向增长) + movl %eax, (%esp)
popl %eax --- 出栈,分两步:movl (%esp), %eax + addl $4, %esp
addl $8, %eax ---
subl $4, %esp ---
enter --- 进入函数,分两步:pushl %ebp + movl %esp, %ebp(将栈顶地址复制给栈基址,当前栈变为空)
leave --- 退出函数,分两步:movl %ebp, %esp + popl %ebp
call 0x12345 --- push %eip + movl 0x12345, %eip(%eip存放下一条执行指令)
ret --- call的逆操作,相当于popl %eip
2,传输字节数
movb 8bit
movw 16bit
movl 32bit
movq 64bit
3,程序实例
int g(int x){
return x + 10;
}
int f(int x){
return g(x);
}
int main(){
return f(20) + 8;
}
执行汇编命令:
gcc -S -o main.s main.c -m32
生成32位汇编代码main.s;
.file "main.c"
.text
.globl g
.type g, @function
g:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
addl $10, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size g, .-g
.globl f
.type f, @function
f:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
.size f, .-f
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl $20, (%esp)
call f
addl $8, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-11)"
.section .note.GNU-stack,"",@progbits
剔除无关精要的部分,核心汇编代码如下:
1 g:
2 pushl %ebp
3 movl %esp, %ebp
4 movl 8(%ebp), %eax
5 addl $10, %eax
6 popl %ebp
7 ret
8 f:
9 pushl %ebp
10 movl %esp, %ebp
11 subl $4, %esp
12 movl 8(%ebp), %eax
13 movl %eax, (%esp)
14 call g
15 leave
16 ret
17 main:
18 pushl %ebp
19 movl %esp, %ebp
20 subl $4, %esp
21 movl $20, (%esp)
22 call f
23 addl $8, %eax
24 leave
25 ret