Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc 为什么ELF对象文件包含字符串文本和stdlib函数的虚拟地址?_Gcc_Assembly_Disassembly - Fatal编程技术网

Gcc 为什么ELF对象文件包含字符串文本和stdlib函数的虚拟地址?

Gcc 为什么ELF对象文件包含字符串文本和stdlib函数的虚拟地址?,gcc,assembly,disassembly,Gcc,Assembly,Disassembly,我用C写了这个Hello World: #include<stdio.h> int main() { printf("Hello world !\n"); return 0; } 没问题。但是现在,我想将汇编代码与由objdump反汇编的代码进行比较: 对于主要功能,我得到以下信息: .file "file.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "Hello

我用C写了这个Hello World:

#include<stdio.h>

int main() {
  printf("Hello world !\n");
  return 0;
}
没问题。但是现在,我想将汇编代码与由objdump反汇编的代码进行比较:

对于主要功能,我得到以下信息:

    .file   "file.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Hello world !"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB1:
    .section    .text.startup,"ax",@progbits
.LHOTB1:
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB11:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $.LC0, %edi
    call    puts
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE11:
    .size   main, .-main
    .section    .text.unlikely
.LCOLDE1:
    .section    .text.startup
.LHOTE1:
    .ident  "GCC: (GNU) 4.9.2 20150304 (prerelease)"
    .section    .note.GNU-stack,"",@progbits
0000000000000000 <main>:
   0:   48 83 ec 08             sub    $0x8,%rsp
   4:   bf 00 00 00 00          mov    $0x0,%edi
            5: R_X86_64_32  .rodata.str1.1
   9:   e8 00 00 00 00          callq  e <main+0xe>
            a: R_X86_64_PC32    puts-0x4
   e:   31 c0                   xor    %eax,%eax
  10:   48 83 c4 08             add    $0x8,%rsp
  14:   c3                      retq   
0000000000000000:
0:48 83 ec 08分$0x8,%rsp
4:bf 00 mov$0x0,%edi
5:R_X86_64_32.rodata.str1.1
9:E800呼叫e
a:R_X86_64_PC32 puts-0x4
e:31 c0异或%eax,%eax
10:48 83 c4 08添加$0x8,%rsp
14:c3 retq
我不明白两件事:

为什么在
edi
上移动数字0意味着加载字符串“Hello world”


此外,指令
callq
调用地址
e
。但是地址
e
处的指令不是函数
put
,而是一个
xor
。那么真正的地址是什么呢?

答案是链接器应用了各种修正。当我执行一个
objdump-d hello.o
时,我得到以下结果:

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   bf 00 00 00 00          mov    $0x0,%edi
   9:   e8 00 00 00 00          callq  e <main+0xe>
   e:   b8 00 00 00 00          mov    $0x0,%eax
  13:   5d                      pop    %rbp
  14:   c3                      retq   
不同之处在于,字符串偏移量的零和
put
的地址现在实际上由链接器填充。您可以使用
objdump-r hello.o

hello.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
0000000000000005 R_X86_64_32       .rodata
000000000000000a R_X86_64_PC32     puts-0x0000000000000004
这意味着链接器找到
.rodata
(字符串的地址)的实际地址,并将其置于偏移量
0x5
处,而库的地址
置于偏移量
0xa

更详细地描述了该过程,并正确地指出,虽然某些重定位发生在链接时间,但加载程序也可以提供重定位数据。

这是因为重定位而发生的,我在这里编写了一个教程:
hello.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
0000000000000005 R_X86_64_32       .rodata
000000000000000a R_X86_64_PC32     puts-0x0000000000000004