分段错误来自错误的堆栈对齐( misaligned_stack_error
)。
当您遇到此类问题时,请始终尝试使用 GDB 运行您的程序。它通常会为您提供更多信息。
但是要恢复,当您从 C 库中调用函数时,堆栈需要在16 字节边界上对齐。
这是Mac OS X 32 位 ABI的要求(注意这也是 64 位 ABI 的情况,它使用 SYS V 调用约定)。
所以这是你的程序的一个工作版本,它将打印可执行文件的名称,以及 CLI 参数的数量(解释就在后面):
[bits 32]
section .data
hello db "Program name: %s (%i CLI args)", 10, 0
section .text
global start
extern _exit
extern _printf
start:
; Store 'argc' into EAX
pop eax
; Store 'argv' into EBX
pop ebx
; Align stack on a 16 bytes boundary,
; as we'll use C library functions
mov ebp, esp
and esp, 0xFFFFFFF0
; Stack space for local variables
; A little more space than needed, but that will
; ensure the stack is still aligned
sub esp, 16
; Call 'printf': printf( hello, ebx, eax );
mov dword[ esp ], hello
mov dword[ esp + 4 ], ebx
mov dword[ esp + 8 ], eax
call _printf
; Call 'exit': exit( 0 );
mov dword[ esp ], 0
call _exit
编译它使用:
nasm -f macho -o test.o test.asm
ld -o test test.o -arch i386 -lc -macosx_version_min 10.6
解释:
我们首先在一些寄存器中存储argc
和:argv
pop eax
pop ebx
然后我们在 16 字节边界上对齐堆栈:
mov ebp, esp
and esp, 0xFFFFFFF0
在为局部变量创建空间时start
,假设您保持堆栈对齐,您只能在开始时执行此操作一次。
然后我们为局部变量创建必要的空间,确保堆栈保持对齐。
在这里,我们只需要 3 个堆栈参数的空间,但我们为 4 个创建空间,以保持堆栈对齐。
sub esp, 16
然后,您可以在该空间上移动值,为调用准备参数:
mov dword[ esp ], hello
mov dword[ esp + 4 ], ebx
mov dword[ esp + 8 ], eax
然后只需调用 C 库函数,就可以了。
请注意,您还可以在此答案 (x86 Assembly on a Mac)中找到一些有用的信息。