gcc 程序集字符串表示

Lea*_*dro 2 c string assembly gcc decimal

char a[] = "abc";   // movl    $6513249, -12(%rbp)
char ab[] = "ab";  // movw    $25185, -11(%rbp) 
char abc[] = "a"; // movw    $97, -10(%rbp)
Run Code Online (Sandbox Code Playgroud)

上面的 C 代码在汇编 (gcc -S code.c) 中表示为:

movl    $6513249, -12(%rbp)
movw    $25185, -15(%rbp)
movw    $97, -17(%rbp)
Run Code Online (Sandbox Code Playgroud)

97 是十进制的“a”,但为什么“ab”是 25185 而“abc”是 6513249?

Jea*_*bre 5

让我们取第一行的 32 位整数的十六进制值:

>>> hex(6513249)
'0x636261'
Run Code Online (Sandbox Code Playgroud)

这是 cba

由于处理器是小端的,因此它只是一种优化的方式来初始化一个小字符串,只需 32 位移动,而不是繁琐的逐字节复制。

这里的所有字符串都没有处理 nul-termination(movw $25185, -15(%rbp)sets aand bbut not nul-terminate),它是在你没有显示的代码中的其他地方完成的(请注意,nul-termination 字节有空间:第一个字符串在偏移量 -12,第二个字符串在偏移量 -15 处,这使得它有 3 个字节长,和最后一个相同)

  • 缓冲区是自动的,所以它还没有被清零,但是 6513249 作为一个 long 是 0x00636261,所以空终止符在那里。 (3认同)
  • OP 没有显示周围的代码。gcc 使用单独的指令来存储零,而不是重叠存储或将填充保留为 4B。https://godbolt.org/g/wJir9S。这是一个遗漏的优化:`push imm32` 或 `mov r/m64, imm32` 可以存储 1B 和 2B 字符串,其中一个后面是显式的“0”,另一个后面是隐式的“0”(从符号扩展到 64 位,因为最后一个字符低于 127)。3 字节字符串可以与另一个 4B 存储重叠该存储的最后 3 个字节。堆栈是 16B 对齐的,因此您可以在没有机会跨越缓存线的情况下执行此操作。 (3认同)