简体   繁体   中英

Function call instructions explanation

So, I have recently started understanding x86 assembly language. I made an object file of the following C++ code and used objdump -S to view the .o file created.

void func(){
    int d,f;
    d=10;
    f=1;    
}

int main(){
    int x;
    x = 1;
}

I got the following assembly code :

t1.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z4funcv>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   c7 45 f8 0a 00 00 00    movl   $0xa,-0x8(%rbp)
   b:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
  12:   5d                      pop    %rbp
  13:   c3                      retq   

0000000000000014 <main>:
  14:   55                      push   %rbp
  15:   48 89 e5                mov    %rsp,%rbp
  18:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
  1f:   b8 00 00 00 00          mov    $0x0,%eax
  24:   5d                      pop    %rbp
  25:   c3                      retq

Can someone what exactly the assembly code instructions are doing? I understand that push and pop are used to store and remove from stack . But what is the exact use the instruction is doing?

The calling convention mandates which registers need to be preserved, and that includes rbp . This means, if your function wants to use rbp for its own purposes, it must make sure that it holds the same value at function exit as it did at function entry. A convenient way to achieve this is to push and pop it.

What does it use rbp for? Historically, the bp register has been used to mark the stack frame and to access local variables and function arguments. One of the reasons was that in old 16 bit code, you couldn't address relative to the stack pointer sp . Also, knowing the stack frame boundaries can be helpful in debugging and stack unwinding. In 32 and nowadays in 64 bit code, you can address relative to the stack pointer, and debugging is aided by specialized debug information which works fine even without a frame pointer. As such, it has become common practice to disable frame pointer, effectively freeing one more register for general use. This code has not been compiled with optimization enabled, which is why you see rbp being used.

Okay, let's see what is happening. Line 0 saves rbp as discussed above. Line 1 then saves the current value of the stack pointer there, marking the stack frame. Lines 4 and b simply initialize your two variables. Note that they reside in the 128 byte red zone under the stack pointer that the x86-64 ABI allows you to use without allocating. Normally you'd see a sub rsp, size-of-locals kind of instruction to allocate the space from the stack. Line 12 restores the original value of rbp , and finally line 13 returns to the caller.

The main function is pretty similar, the only interesting difference is on line 1f which loads 0 into eax . That register is used to pass return values back to the caller.

This was just a quick peek into the topic of calling conventions. For the deeper details refer to the appropriate documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM