字符串数据存储在哪里?

kas*_*sky 6 c linux string x86 assembly

我写了一个小c程序:

#include <stdio.h>

int main()
{
    char s[] = "Hello, world!";
    printf("%s\n", s);
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

编译到(在我的linux机器上):

    .file   "hello.c"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax
    movl    $1819043144, -32(%rbp)
    movl    $1998597231, -28(%rbp)
    movl    $1684828783, -24(%rbp)
    movw    $33, -20(%rbp)
    leaq    -32(%rbp), %rax
    movq    %rax, %rdi
    call    puts
    movl    $0, %eax
    movq    -8(%rbp), %rdx
    xorq    %fs:40, %rdx
    je  .L3
    call    __stack_chk_fail
.L3:
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我不明白汇编代码,但我看不到任何字符串消息.那么可执行文件如何知道要打印什么?

Pau*_*l R 12

它在这里:

movl    $1819043144, -32(%rbp) ; 1819043144 = 0x6C6C6548 = "lleH"
movl    $1998597231, -28(%rbp) ; 1998597231 = 0x77202C6F = "w ,o"
movl    $1684828783, -24(%rbp) ; 1684828783 = 0x646C726F = "dlro"
movw    $33, -20(%rbp)         ;         33 =     0x0021 = "\0!"
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,编译器生成内联指令以在调用之前生成文字字符串常量printf.当然在其他情况下它可能不会这样做,但可能会将字符串常量存储在内存的另一部分中.结论:您无法对编译器生成和存储字符串文字的方式和位置做出任何假设.