How would you explain this disassembly listing?

…衆ロ難τιáo~ 提交于 2021-01-28 04:13:57

问题


I have a simple function in C language, in separate file string.c:

void var_init(){
    char *hello = "Hello";
}

compiled with:

gcc -ffreestanding -c string.c -o string.o

And then I use command

objdump -d string.o

to see disassemble listing. What I got is:

string.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <var_init>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # b <var_init+0xb>
   b:   48 89 45 f8             mov    %rax,-0x8(%rbp)
   f:   90                      nop
  10:   5d                      pop    %rbp
  11:   c3                      retq

I lost in understanding this listing. The book "Writing OS from scratch" says something about old disassembly and slightly uncover the mistery, but their listing is completely different and I even not see that data interpreted as code in mine as author says.


回答1:


This command

lea    0x0(%rip),%rax

stores the address of the string literal in the register rax.

And this command

mov    %rax,-0x8(%rbp)

copies the address from the register rax into the allocated stack memory. The address occupies 8 bytes as it is seen from the offset in the stack -0x8.

This store only happens at all because you compiled in debug mode; it would normally be optimized away. The next thing that happens is that the local vars (in the red-zone below the stack pointer) are effectively discarded as the function tears down its stack frame and returns.

The material you're looking at probably included a sub $16, %rsp or similar to allocate space for locals below RBP, then deallocating that space later; the x86-64 System V ABI doesn't need that in leaf functions (that don't call any other functions); they can just use the read zone. (See also Where exactly is the red zone on x86-64?). Or compile with gcc -mno-red-zone, which you probably want anyway for freestanding code: Why can't kernel code use a Red Zone

Then it restores the saved value of the caller's RBP (which was earlier set up as a frame pointer; notice that space for locals was addressed relative to RBP).

pop    %rbp

and exits, effectively popping the return address into RIP

retq



回答2:


In addition to the explaination from @VladfromMoscow, Just thought it might be helpful for the poster to see what happens when you compile to assembly rather than using objdump to see it, as the data can be seen more plainly then (IMO) and the RIP relative addressing may make a bit more sense.

gcc -S x.s

Yields

    .file   "x.c"
    .text
    .section    .rodata
.LC0:
    .string "Hello"
    .text
    .globl  var_init
    .type   var_init, @function
var_init:
.LFB0:
    pushq   %rbp
    movq    %rsp, %rbp
    leaq    .LC0(%rip), %rax
    movq    %rax, -8(%rbp)
    nop
    popq    %rbp
    ret
.LFE0:
    .size   var_init, .-var_init
    .ident  "GCC: (Alpine 8.3.0) 8.3.0"
    .section    .note.GNU-stack,"",@progbits



来源:https://stackoverflow.com/questions/59781879/how-would-you-explain-this-disassembly-listing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!