linux汇编之——(4)最简C代码

在最简代码的基础上进行 反汇编看汇编代码

    int main()
    {
        return 0;
    }   

    编译该程序,产生二进制文件:
    # gcc test0.c -o test0
    # file test0  
    test0: ELF 32-bit LSBexecutable 80386 Version 1, dynamically linked, not stripped
 

    test0
是一个ELF格式32位小端(Little Endian)的可执行文件,动态链接并且符号表没有去除。

使用objdump命令

$ objdump -d test

其反汇编代码如下

080483b4 <main>:

 80483b4:    55                        push   %ebp

 80483b5:    89 e5                     mov    %esp,%ebp

 80483b7:    b8 00 00 00 00             mov    $0x0,%eax

 80483bc:     5d                        pop    %ebp

 80483bd:    c3                        ret   

用gdb进行反编译,disas是disassemble的缩写

(gdb) disas main

Dump of assembler code for function main:

  0x080483b4 <+0>:       push   %ebp                    ;ebp寄存器内容压栈,即保存调用main函数的上级函数的栈基地址

  0x080483b5 <+1>:       mov    %esp,%ebp   ;esp值赋值给ebp,设置main函数的基地址

  0x080483b7 <+3>:       mov    $0x0,%eax     ;设置main函数返回值为0

  0x080483bc <+8>: pop    %ebp                    ;pop先前栈内的上级函数栈的地址给ebp,即恢复原栈基址

  0x080483bd <+9>:       ret                            ;main函数返回,回到上级调用

End of assembler dump.

 

问题:谁调用了 main函数?

在C语言的层面来看,main函数是一个程序的起始入口点,而实际上,ELF可执行文件的入口点并不是main而是_start。

    gdb也可以反汇编_start

(gdb) disas _start

Dump of assembler code for function _start:

  0x08048300 <+0>:       xor    %ebp,%ebp

  0x08048302 <+2>:       pop    %esi

  0x08048303 <+3>:       mov    %esp,%ecx

  0x08048305 <+5>:       and    $0xfffffff0,%esp

  0x08048308 <+8>:       push   %eax

   0x08048309<+9>:       push   %esp

  0x0804830a <+10>:     push   %edx

  0x0804830b <+11>:     push   $0x80483c0

  0x08048310 <+16>:     push   $0x80483d0

  0x08048315 <+21>:     push   %ecx

  0x08048316 <+22>:     push   %esi

  0x08048317 <+23>:     push   $0x80483b4

  0x0804831c <+28>:      call   0x80482e8 <__libc_start_main@plt>

  0x08048321 <+33>:     hlt   

  0x08048322 <+34>:     nop

  0x08048323 <+35>:     nop

  0x08048324 <+36>:     nop

  0x08048325 <+37>:     nop

  0x08048326 <+38>:     nop

  0x08048327 <+39>:     nop

  0x08048328 <+40>:     nop

   0x08048329 <+41>:     nop

问题:为什么用EAX寄存器保存函数返回值?
    实际上IA32并没有规定用哪个寄存器来保存返回值。但如果反汇编Solaris/Linux的二进制文件,就会发现,都用EAX保存函数返回值。
    这不是偶然现象,是操作系统的ABI(Application Binary Interface)来决定的。
    Solaris/Linux操作系统的ABI就是Sytem V ABI。



你可能感兴趣的:(linux汇编之——(4)最简C代码)