源码:
int foobar(int a, int b, int c)
{
int xx = a + 2;
int yy = b + 3;
int zz = c + 4;
int sum = xx + yy + zz;
return xx * yy * zz + sum;
}
int main()
{
return foobar(77, 88, 99);
}
汇编:
gcc -masm=intel -S z.c -o z.s
z.s 源码:
.file "z.c"
.intel_syntax
.text
.globl foobar
.type foobar, @function
foobar:
.LFB2:
push %rbp
.LCFI0:
mov %rbp, %rsp
.LCFI1:
mov DWORD PTR [%rbp-20], %edi
mov DWORD PTR [%rbp-24], %esi
mov DWORD PTR [%rbp-28], %edx
mov %eax, DWORD PTR [%rbp-20]
add %eax, 2
mov DWORD PTR [%rbp-16], %eax
mov %eax, DWORD PTR [%rbp-24]
add %eax, 3
mov DWORD PTR [%rbp-12], %eax
mov %eax, DWORD PTR [%rbp-28]
add %eax, 4
mov DWORD PTR [%rbp-8], %eax
mov %eax, DWORD PTR [%rbp-12]
add %eax, DWORD PTR [%rbp-16]
add %eax, DWORD PTR [%rbp-8]
mov DWORD PTR [%rbp-4], %eax
mov %eax, DWORD PTR [%rbp-16]
imul %eax, DWORD PTR [%rbp-12]
imul %eax, DWORD PTR [%rbp-8]
add %eax, DWORD PTR [%rbp-4]
leave
ret
.LFE2:
.size foobar, .-foobar
.globl main
.type main, @function
main:
.LFB3:
push %rbp
.LCFI2:
mov %rbp, %rsp
.LCFI3:
mov %edx, 99
mov %esi, 88
mov %edi, 77
call foobar
leave
ret
.LFE3:
.size main, .-main
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI2-.LFB3
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI3-.LCFI2
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE3:
.ident "GCC: (GNU) 4.1.2 20070115 (prerelease) (SUSE Linux)"
.section .note.GNU-stack,"",@progbits
现在我们只关注
main 函数和 foobar 这两个函数, 也就是下面这一块代码
foobar:
.LFB2:
push %rbp
.LCFI0:
mov %rbp, %rsp
.LCFI1:
mov DWORD PTR [%rbp-20], %edi
mov DWORD PTR [%rbp-24], %esi
mov DWORD PTR [%rbp-28], %edx
mov %eax, DWORD PTR [%rbp-20]
add %eax, 2
mov DWORD PTR [%rbp-16], %eax
mov %eax, DWORD PTR [%rbp-24]
add %eax, 3
mov DWORD PTR [%rbp-12], %eax
mov %eax, DWORD PTR [%rbp-28]
add %eax, 4
mov DWORD PTR [%rbp-8], %eax
mov %eax, DWORD PTR [%rbp-12]
add %eax, DWORD PTR [%rbp-16]
add %eax, DWORD PTR [%rbp-8]
mov DWORD PTR [%rbp-4], %eax
mov %eax, DWORD PTR [%rbp-16]
imul %eax, DWORD PTR [%rbp-12]
imul %eax, DWORD PTR [%rbp-8]
add %eax, DWORD PTR [%rbp-4]
leave
ret
.LFE2:
.size foobar, .-foobar
.globl main
.type main, @function
main:
.LFB3:
push %rbp
.LCFI2:
mov %rbp, %rsp
.LCFI3:
mov %edx, 99
mov %esi, 88
mov %edi, 77
call foobar
leave
ret
ebp : 扩展基址指针寄存器(extended base pointer) 其内存放一个指针,该指针指向系统栈最上面一个栈帧的底部。(rbp 64bit 作用同 ebp )
64bit 参数传递
%rdi | %rsi | %rdx | %r10 | %r8 | %r9 |
参数一 | 参数二 | 参数三 | 参数四 | 参数五 | 参数六 |
main:
.LFB3:
push %rbp
.LCFI2:
mov %rbp, %rsp
.LCFI3:
mov %edx, 99
mov %esi, 88
mov %edi, 77
call foobar
leave
ret
所以这里 foobar 三个参数 在 main 调用 分别对应
return foobar(77, 88, 99);
77->rdi
88->rsi
99->rdx
下面在来看看 foobar 函数:
foobar:
.LFB2:
push %rbp
.LCFI0:
mov %rbp, %rsp
.LCFI1:
mov DWORD PTR [%rbp-20], %edi
mov DWORD PTR [%rbp-24], %esi
mov DWORD PTR [%rbp-28], %edx
mov %eax, DWORD PTR [%rbp-20]
add %eax, 2
mov DWORD PTR [%rbp-16], %eax
mov %eax, DWORD PTR [%rbp-24]
add %eax, 3
mov DWORD PTR [%rbp-12], %eax
mov %eax, DWORD PTR [%rbp-28]
add %eax, 4
mov DWORD PTR [%rbp-8], %eax
mov %eax, DWORD PTR [%rbp-12]
add %eax, DWORD PTR [%rbp-16]
add %eax, DWORD PTR [%rbp-8]
mov DWORD PTR [%rbp-4], %eax
mov %eax, DWORD PTR [%rbp-16]
imul %eax, DWORD PTR [%rbp-12]
imul %eax, DWORD PTR [%rbp-8]
add %eax, DWORD PTR [%rbp-4]
leave
ret
前面 16 字节 主要用来在计算过程中做一些临时的存储. 对着代码就比较容易理解了
其他的就不具体多说了。