关于macOS:Mac OS X组装和系统调用导致总线错误10

Mac OS X assembly and sys call causing Bus Error 10

试图在Macbook Pro(Intel i7,64位)上运行程序集,并且遇到了奇怪的错误。

这是一个基本的"你好,世界!" 仅使用系统调用来编程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SECTION .text
global start

start:
mov rax, 2
shl rax, 24
add al , 4
mov rdi, 1
mov rsi, Msg
mov rdx, Len
syscall

mov al , 1
mov rdi, 0
syscall

SECTION .data
Msg db `Hello, world!
`
Len: equ $-Msg

与NASM 2.11组装
控制台命令:

1
2
nasm -f macho64 -o main.o main.s
ld main.o

它显示" Hello,world"和换行符,但随后返回总线错误:10(错误的内存地址)。

但是如果我这样做:

1
2
3
mov rax, 2
shl rax, 24
add al , 1

我没有公交车错误。

问题是:为什么我不能使用" mov al,1"来更改不同调用的rax的第一个字节


rax寄存器不会被第一个syscall保留,因此仅将al设置为1并不能为您提供正确的值,因为它不会影响所有rax中的下一个系统调用。 不给您总线错误的方法是重新填充rax的所有位的方法。

由于write是要返回实际写入的字节数,因此返回到rax,从而确保您需要为下一个syscall完全填充它。 可以在Wikipedia调用约定页面上找到对rax用于返回码的支持,该页面指出System V AMD64 ABI

The calling convention of the System V AMD64 ABI[11] is followed on Solaris, GNU/Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems. The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9, while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments. For system calls, R10 is used instead of RCX.[11] As in the Microsoft x64 calling convention, additional arguments are passed on the stack and the return value is stored in RAX.

附录A中的" System V应用程序二进制接口"," AMD64体系结构处理器增补"文档中也对此进行了详细说明。

在修复代码方面,最好进行完整的填充序列(不进行不必要的移位):

1
2
3
mov rax, 0x2000001
mov rdi, 0
syscall

退出。 实际上,我将对两个系统调用都使用该方法以简化源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SECTION .text
global start

start:
mov rax, 0x2000004      ; syscall 4: write (
mov rdi, 1              ;    fd,
mov rsi, Msg            ;    buffer,
mov rdx, Len            ;    size
syscall                 ; )

mov rax, 0x2000001      ; syscall 1: exit (
mov rdi, 0              ;    retcode
syscall                 ; )

SECTION .data
Msg db `Hello, world!
`
Len: equ $-Msg