1. 程式人生 > >關於AT&T彙編和c語言的相互呼叫的分析

關於AT&T彙編和c語言的相互呼叫的分析

這方面很多人寫了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


這裡主要注意將引數壓棧的順序