關於AT&T彙編和c語言的相互呼叫的分析
阿新 • • 發佈:2019-01-21
這方面很多人寫了blog,這次我也是學習,從objdump等工具分析。
------------------------c中調用匯編-------------------------------
首先給出c檔案
#include<stdio.h>
int main()
{
int j;
j=add(3);
printf("add(3) is %d\n",j);
}
add是用匯編完成的,看看c如何呼叫這個函式,當然這裡的add不僅僅可以用匯編寫,其他都可以,只是函式的一個入口地址。
利用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) <span style="color:#ff0000;"> call _add</span> movl %eax, 28(%esp) movl 28(%esp), %eax movl %eax, 4(%esp) movl $LC0, (%esp) <span style="color:#ff0000;">call _printf</span> 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>: <span style="color:#009900;"> 0: 55 push %ebp 這裡是為了對齊暫時不研究 1: 89 e5 mov %esp,%ebp 3: 83 e4 f0 and $0xfffffff0,%esp 6: 83 ec 20 sub $0x20,%esp</span> <span style="color:#3333ff;"> 9: e8 00 00 00 00 call e <_main+0xe> 這是在呼叫函式之前完成的事情 e: c7 04 24 03 00 00 00 movl $0x3,(%esp) 將立即數3壓入棧中,</span> 15: e8 1a 00 00 00 <span style="color:#ff0000;">call 34 <_add> 呼叫add函式</span> 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<stdio.h>
int main()
{
int result;
int i,j;
i=2;j=3;
result=add(i,j);
printf("add(3) is %d\n",j);
}
add為
.globl _add
.section .text
_add:
pushl %ebp
movl %esp,%ebp
<span style="color:#ff0000;">movl 8(%ebp),%eax i的值
movl 12(%ebp),%ecx j的值</span>
addl %ecx,%eax
movl %ebp,%esp
popl %ebp
ret
將main.c編譯成.s檔案為(部分)
_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
<span style="color:#ff0000;">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的值</span>
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
這裡主要注意將引數壓棧的順序