使用多个db声明时,NASM编译x86_64 ASM标签在Mach-O中关闭256个字节?

Ale*_*ara 4 assembly x86-64 mach-o nasm data-segment

简而言之,当我db在我的.data部分中有多个部分时,编译的地址/标签在NASM编译时关闭.在我的测试中,它们在得到的Mach-O二进制文件中关闭了256个字节.

我使用的软件:

  • OS X 10.10.5
  • nasm NASM版本2.11.08,根据x84_64 ASM的要求通过Homebrew安装
  • gobjdump GNU objdump(GNU Binutils)2.25.1,通过Homebrew安装
  • clang Apple LLVM版本6.1.0(clang-602.0.53)(基于LLVM 3.6.0svn)

什么有效:

以下面的"hello world"NASM程序集为例.

main.s

global _main

section .text
_main:
mov     rax, 0x2000004
mov     rdi, 1
lea     rsi, [rel msg]
mov     rdx, len
syscall

mov     rax, 0x2000001
mov     rdi, 0
syscall

section .data
msg:    db      "Hello, world!", 10
len:    equ     $ - msg
Run Code Online (Sandbox Code Playgroud)

编译并运行:

/usr/local/bin/nasm -f macho64 -o main.o main.s
clang -o main main.o
./main
Run Code Online (Sandbox Code Playgroud)

这很好用,并产生以下输出:

Hello, world!
Run Code Online (Sandbox Code Playgroud)

什么不:

现在,要添加另一条消息,我们只需要在数据部分添加另一个字符串,另一个syscall.很简单.

main.s

global _main

section .text
_main:
mov     rax, 0x2000004
mov     rdi, 1
lea     rsi, [rel msga]
mov     rdx, lena
syscall

mov     rax, 0x2000004
mov     rdi, 1
lea     rsi, [rel msgb]
mov     rdx, lenb
syscall

mov     rax, 0x2000001
mov     rdi, 0
syscall

section .data
msga:    db      "Hello, world!", 10
lena:    equ     $ - msga
msgb:    db      "Break things!", 10
lenb:    equ     $ - msgb
Run Code Online (Sandbox Code Playgroud)

编译并运行,和以前一样,我们得到:

Break things!
Run Code Online (Sandbox Code Playgroud)

什么?!?我们不应该得到吗?:

Hello, world!
Break things!
Run Code Online (Sandbox Code Playgroud)

怎么了?:

显然出了点问题.是时候拆解生成的二进制文件,看看我们得到了什么.

$ gobjdump -d -M intel main
Run Code Online (Sandbox Code Playgroud)

产生以下内容_main:

0000000100000f7c <_main>:
   100000f7c:b8 04 00 00 02       mov    eax,0x2000004
   100000f81:bf 01 00 00 00       mov    edi,0x1
   100000f86:48 8d 35 73 01 00 00 lea    rsi,[rip+0x173]        # 100001100 <msgb+0xf2>
   100000f8d:ba 0e 00 00 00       mov    edx,0xe
   100000f92:0f 05                syscall 
   100000f94:b8 04 00 00 02       mov    eax,0x2000004
   100000f99:bf 01 00 00 00       mov    edi,0x1
   100000f9e:48 8d 35 69 00 00 00 lea    rsi,[rip+0x69]        # 10000100e <msgb>
   100000fa5:ba 0e 00 00 00       mov    edx,0xe
   100000faa:0f 05                syscall 
   100000fac:b8 01 00 00 02       mov    eax,0x2000001
   100000fb1:bf 00 00 00 00       mov    edi,0x0
   100000fb6:0f 05                syscall 
Run Code Online (Sandbox Code Playgroud)

从注释中# 100001100 <msgb+0xf2>,我们可以看到它指向的不是msga符号,而是指向0xf2过去msgb,或者100001100(在此地址处有空字节,导致无输出).在十六进制编辑器中检查二进制文件,我msga在偏移量1000或地址处找到实际的字符串100001000.这意味着编译后的二进制文件中的地址现在被0x100/ 256字节关闭,这只是因为现在有第二个db标签.什么?!?


一个解决方法的遗憾:

作为一个实验,我决定尝试将两个db部分放入单独的ASM /目标文件中,并将所有3个部分链接在一起.这样做有效.

main.s

global _main
extern _msga
extern _lena
extern _msgb
extern _lenb

section .text
_main:
mov     rax, 0x2000004
mov     rdi, 1
lea     rsi, [rel _msga]
mov     rdx, _lena
syscall

mov     rax, 0x2000004
mov     rdi, 1
lea     rsi, [rel _msgb]
mov     rdx, _lenb
syscall

mov     rax, 0x2000001
mov     rdi, 0
syscall
Run Code Online (Sandbox Code Playgroud)

msga.s

global _msga
global _lena

section .data
_msga:   db      "Hello, world!", 10
_lena:   equ     $ - _msga
Run Code Online (Sandbox Code Playgroud)

msgb.s

global _msgb
global _lenb

section .data
_msgb:   db      "Break things!", 10
_lenb:   equ     $ - _msgb
Run Code Online (Sandbox Code Playgroud)

编译并运行:

/usr/local/bin/nasm -f macho64 -o main.o main.s
/usr/local/bin/nasm -f macho64 -o msga.o msga.s
/usr/local/bin/nasm -f macho64 -o msgb.o msgb.s
clang -o main msga.o msgb.o main.o
./main
Run Code Online (Sandbox Code Playgroud)

结果是:

Hello, world!
Break things!
Run Code Online (Sandbox Code Playgroud)

虽然这确实有效,但我发现很难相信这是最好的解决方案.


出了什么问题?

当然必须有一种方法db在一个ASM文件中有多个标签?我在编写ASM的方式上做错了吗?这是NASM中的错误吗?是这种预期的行为,在哪种情况下为什么?我的解决方法是额外的工作和混乱,所以我非常感谢任何帮助.

Fra*_*ler 6

是的,这是Nasm-2.11.08中的一个错误.Nasm-2.11.06应该可以工作.Nasm-2.11.09rc1应该工作(?).对不起'那个!