NASM 的尴尬数据部分行为

Awkward data section behavior with NASM

我正在用汇编编写一些基本程序,其中我只是进行一些函数调用。我在 OS X 上,使用 Mach-O 64 位格式。但是,我对数据部分的理解似乎存在缺陷。我了解到data段是用来存放初始化数据的,所以决定初始化两块内存,如下图:

default rel

global _main
extern _puts

section .data
    first db "Message A", 0 ; null terminator
    second db "Message B", 0

section .text

_main:
    push rbp ; alignment
    mov rbp, rsp
    sub rsp, 0x10
    lea rdi, [second]
    call _puts
    lea rdi, [first]
    call _puts
    add rsp, 0x10
    pop rbp
    ret

(显然我链接的是 libc)

我的理解是,根据 System V ABI 规范,堆栈必须是 16 字节对齐的。此外,rdi 应该包含函数调用的第一个参数。

上面的代码会打印"Message B",但是后面直接打印"Message A"就失败了。好像 "Message A" 在某处被覆盖了。

同样有趣的是,当我在 .text 部分输入两个字符串时,代码按预期工作。由于 .text 是只读的,我几乎可以肯定 "Message A" 在初始化后的某个时间被覆盖。无论我在 .data 部分输入多少个字符串,我只能打印最后一个,其他的都被覆盖。为什么最后一个初始化的字符串是唯一没有被覆盖的?

目前,似乎没有太多解决办法。这是 2.11.08 中的一个错误,我想有些人也报告了 2.11.06 的问题,所以去 2.11.05 可能是你最好的选择,或者等待 2.11.09。