从C转换为汇编时,以null结尾的字符串在哪里?

sag*_*a.x 7 c linux x86 gcc

我制作了两个程序来输出两个字符串,一个在汇编中,另一个在C中.这是程序集中的程序:

.section .data
string1:
.ascii "Hola\0"
string2:
.ascii "Adios\0"

.section .text
.globl _start
_start:

pushl $string1
call puts
addl $4, %esp

pushl $string2
call puts
addl $4, %esp

movl $1, %eax
movl $0, %ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)

我用它构建程序

as test.s -o test.o
ld -dynamic-linker /lib/ld-linux.so.2 -o test test.o -lc
Run Code Online (Sandbox Code Playgroud)

输出正如预期的那样

Hola
Adios
Run Code Online (Sandbox Code Playgroud)

这是C程序:

#include <stdio.h>
int main(void)
{
    puts("Hola");
    puts("Adios");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到了预期的输出,但是当使用gcc -S(OS是Debian 32位)将此C程序转换为汇编时,输出汇编源代码不包括两个字符串中的空字符,如下所示:

    .file   "testc.c"
    .section    .rodata
.LC0:
    .string "Hola"
.LC1:
    .string "Adios"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    leal    4(%esp), %ecx
    .cfi_def_cfa 1, 0
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    .cfi_escape 0x10,0x5,0x2,0x75,0
    movl    %esp, %ebp
    pushl   %ecx
    .cfi_escape 0xf,0x3,0x75,0x7c,0x6
    subl    $4, %esp
    subl    $12, %esp
    pushl   $.LC0
    call    puts
    addl    $16, %esp
    subl    $12, %esp
    pushl   $.LC1
    call    puts
    addl    $16, %esp
    movl    $0, %eax
    movl    -4(%ebp), %ecx
    .cfi_def_cfa 1, 0
    leave
    .cfi_restore 5
    leal    -4(%ecx), %esp
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 4.9.2-10) 4.9.2"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我的两个问题是:

1)为什么gcc生成的汇编代码不会在两个字符串的末尾附加空字符?我以为C自动完成了这个.

2)如果我跳过手工制作的汇编代码中的空字符,我得到这个输出:

HolaAdios
Adios
Run Code Online (Sandbox Code Playgroud)

我理解为什么我在第一行得到"HolaAdios"部分,但为什么程序在"Adios"部分之后成功结束,如果它不是以空终止的?

小智 5

  1. .string总是附加一个空结束,因为看到这里.
  2. 好吧,你可以自己检查一下.puts继续,直到它看到一个空字节.\x00s非常常见,附近必须有一个它可以工作(可能是由于部分对齐.rodata).