这方面很多人写了blog,这次我也是学习,从objdump等工具分析。
------------------------c中调用汇编-------------------------------
首先给出c文件
#include
int main()
{
int j;
j=add(3);
printf("add(3) is %d\n",j);
}
利用gcc -S main.c -o main.s 看看汇编代码
$ cat main.s
.file "main.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "add(3) is %d\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $3, (%esp)
call _add
movl %eax, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
.ident "GCC: (GNU) 4.8.1"
.def _add; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
从中可以看到两次调用(红色),也就是add的入口标签为_add.
下面为add的汇编函数
.globl _add
.section .text
_add:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
imull %eax,%eax
movl %ebp,%esp
popl %ebp
ret
这里会说到c样式的函数调用,即参数传递通过栈。
看看示意图
此汇编的前提就是在call _add 之前就要将要传递的时放到stack中。
为此将main,c add.s 汇编成 mian.o
gcc -o main.o main.c add.s
如下:
main.o: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp 这里是为了对齐暂时不研究
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: e8 00 00 00 00 call e <_main+0xe> 这是在调用函数之前完成的事情
e: c7 04 24 03 00 00 00 movl $0x3,(%esp) 将立即数3压入栈中,
15: e8 1a 00 00 00 call 34 <_add> 调用add函数
1a: 89 44 24 1c mov %eax,0x1c(%esp)
1e: 8b 44 24 1c mov 0x1c(%esp),%eax
22: 89 44 24 04 mov %eax,0x4(%esp)
26: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2d: e8 00 00 00 00 call 32 <_main+0x32>
32: c9 leave
33: c3 ret
00000034 <_add>:
34: 55 push %ebp
35: 89 e5 mov %esp,%ebp
37: 8b 45 08 mov 0x8(%ebp),%eax
3a: 0f af c0 imul %eax,%eax
3d: 89 ec mov %ebp,%esp
3f: 5d pop %ebp
40: c3 ret
41: 90 nop
42: 90 nop
43: 90 nop
Disassembly of section .rdata:
00000000 <.rdata>:
0: 61 popa
1: 64 64 28 33 fs sub %dh,%fs:(%ebx)
5: 29 20 sub %esp,(%eax)
7: 69 73 20 25 64 0a 00 imul $0xa6425,0x20(%ebx),%esi
...
Disassembly of section .rdata$zzz:
00000000 <.rdata$zzz>:
0: 47 inc %edi
1: 43 inc %ebx
2: 43 inc %ebx
3: 3a 20 cmp (%eax),%ah
5: 28 47 4e sub %al,0x4e(%edi)
8: 55 push %ebp
9: 29 20 sub %esp,(%eax)
b: 34 2e xor $0x2e,%al
d: 38 2e cmp %ch,(%esi)
f: 31 00 xor %eax,(%eax)
11: 00 00 add %al,(%eax)
...
Disassembly of section .eh_frame:
00000000 <.eh_frame>:
0: 14 00 adc $0x0,%al
2: 00 00 add %al,(%eax)
4: 00 00 add %al,(%eax)
6: 00 00 add %al,(%eax)
8: 01 7a 52 add %edi,0x52(%edx)
b: 00 01 add %al,(%ecx)
d: 7c 08 jl 17 <.eh_frame+0x17>
f: 01 1b add %ebx,(%ebx)
11: 0c 04 or $0x4,%al
13: 04 88 add $0x88,%al
15: 01 00 add %eax,(%eax)
17: 00 1c 00 add %bl,(%eax,%eax,1)
1a: 00 00 add %al,(%eax)
1c: 1c 00 sbb $0x0,%al
1e: 00 00 add %al,(%eax)
20: 04 00 add $0x0,%al
22: 00 00 add %al,(%eax)
24: 34 00 xor $0x0,%al
26: 00 00 add %al,(%eax)
28: 00 41 0e add %al,0xe(%ecx)
2b: 08 85 02 42 0d 05 or %al,0x50d4202(%ebp)
31: 70 c5 jo fffffff8 <_add+0xffffffc4>
33: 0c 04 or $0x4,%al
35: 04 00 add $0x0,%al
...
------------------------------
几个问题:
1:将汇编中_add换成add
无法识别
--------------------两个参数的传递---------------------------------------------------------------------------------------
将上面稍稍修改一下
#include
int main()
{
int result;
int i,j;
i=2;j=3;
result=add(i,j);
printf("add(3) is %d\n",j);
}
.globl _add
.section .text
_add:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax i的值
movl 12(%ebp),%ecx j的值
addl %ecx,%eax
movl %ebp,%esp
popl %ebp
ret
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $2, 28(%esp)
movl $3, 24(%esp)
movl 24(%esp), %eax
movl %eax, 4(%esp) j的值
movl 28(%esp), %eax
movl %eax, (%esp) i的值
call _add
movl %eax, 20(%esp)
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
这里主要注意将参数压栈的顺序