这个 x86 汇编代码如何创建一个字符串?

How does this x86 Assembly code create a string?

我正在学习x86汇编语言。为了更好地理解字符串创建幕后发生的事情,我有一个示例程序,它只打印一个字符串。 GCC 生成了以下汇编程序,我无法理解编译器的输出:

汇编代码:

Dump of assembler code for function main:
   0x0000000000400596 <+0>: push   %rbp
   0x0000000000400597 <+1>: mov    %rsp,%rbp
   0x000000000040059a <+4>: sub    [=10=]x10,%rsp
   0x000000000040059e <+8>: movq   [=10=]x400668,-0x8(%rbp)
   0x00000000004005a6 <+16>:    mov    -0x8(%rbp),%rax
   0x00000000004005aa <+20>:    mov    %rax,%rsi
=> 0x00000000004005ad <+23>:    mov    [=10=]x400675,%edi
   0x00000000004005b2 <+28>:    mov    [=10=]x0,%eax
   0x00000000004005b7 <+33>:    callq  0x4004a0 <printf@plt>
   0x00000000004005bc <+38>:    mov    [=10=]x0,%eax
   0x00000000004005c1 <+43>:    leaveq 
   0x00000000004005c2 <+44>:    retq 

C代码:

#include <stdio.h>
int main()
{
char *me = "abcdefghijkl";
printf("%s",me);
}

在概念层面上,我知道堆栈指针被减去以在堆栈上分配内存,然后不知何故,这是我在理解[的机制时遇到困难的部分=25=],程序创建字符串。

有人可以帮忙吗? 谢谢

如果你使用-S标志到gcc为你的程序创建一个程序集文件(gcc -S asm.c),那就更清楚了。这会生成一个 asm.s 文件:

        .file   "asm.c"
        .section        .rodata
.LC0:
        .string "abcdefghijkl"
.LC1:
        .string "%s"
        .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    , %rsp
        movq    $.LC0, -8(%rbp)
        movq    -8(%rbp), %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    [=10=], %eax
        call    printf
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-36)"
        .section        .note.GNU-stack,"",@progbits

从这里可以看出,该字符串只是 .rodata 部分中分配了标签 .LC0 的一些初始化内存。更改内存会更改字符串。