简体   繁体   English

从NASM调用C函数_printf会导致分段错误

[英]Calling the C-function _printf from NASM causes a Segmentation Fault

I've been trying to learn 64-bit assembly on both Mac-OS and Windows using NASM. 我一直在尝试使用NASM在Mac-OS和Windows上学习64位汇编。

My code is 我的代码是

extern _printf

section .data
    msg db "Hello World!", 10, 0

section .text
    global _main

_main:
    mov rax, 0
    mov rdi, msg
    call _printf

    mov rax, 0x2000001
    mov rdi, 0
    syscall

and I compile it with 我用它编译

nasm -f macho64 -o main.o main.asm 
gcc -o main main.o

While trying to call _printf , I got the error 尝试调用_printf ,出现错误

Segmentation fault: 11 细分错误:11

When I remove the call to _printf , my code runs fine. 当我删除对_printf的调用时,我的代码运行良好。 Why does the call to _printf cause a segmentation fault? 为什么调用_printf会导致分段错误?

I have found the ABI Calling Convention here , but had no luck successfully calling a C-function. 在这里找到了ABI调用约定,但是不能成功调用C函数。

I would expect Hello World! 我希望Hello World! to be printedd, however I get 'Segmentation Fault: 11' instead. 进行打印,但是我得到的是“ Segmentation Fault:11”。

~~You need to setup a stack frame before calling _printf ~~您需要在调用 _printf之前设置堆栈框架

TL;DR: The System V AMD64 ABI requires the stack-pointer to be 16-byte-aligned. TL; DR: System V AMD64 ABI要求堆栈指针必须是16字节对齐的。 By the time of calling _printf , the stack-pointer is misaligned by 8 bytes. 在调用_printf ,堆栈指针未对齐8个字节。

Debugging the binary with LLDB gives: 使用LLDB调试二进制文件可以得到:

frame #0: 0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error 帧#0:0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error

MacOS uses the System V AMD64 ABI and therefore relies on 16-byte alignment for the stack-pointer ( see this question ), in short this means the stack-pointer ( rsp ) should always be divisible by 16 when calling a function. MacOS使用System V AMD64 ABI,因此堆栈指针依赖16字节对齐( 请参阅此问题 ),简而言之,这意味着调用函数时,堆栈指针( rsp )应始终可被16整除。

By the time of calling _printf , the stack-pointer ( rsp ) is misaligned by 8 bytes. 在调用_printf ,堆栈指针( rsp )未对齐8个字节。 How did this come? 这是怎么来的?

I found the answer on this page , calling the _main function pushes the return address (8 bytes) on the stack and therefore misaligns it. 我在此页面上找到了答案,调用_main函数会将返回地址(8个字节)压入堆栈,因此未对齐。

My initial idea - the setup of the stack frame - pushed another address on the stack and therefore rsp was divisible by 16 again. 我最初的想法-堆栈框架的设置-将另一个地址压入堆栈,因此rsp可以再次被16整除。

However an easier solution would be just sub rsp, 8 as suggested by Margaret Bloom 但是sub rsp, 8Margaret Bloom所建议的sub rsp, 8更简单的解决方案是sub rsp, 8

Change your code to: 将您的代码更改为:

extern _printf

section .data
    msg: db "Hello World!", 10, 0

section .text
    global _main

_main:
    ;; Fix the stack alignment
    sub rsp, 8
    mov rax, 0
    mov rdi, msg
    call _printf

    mov rax, 0x2000001
    mov rdi, 0
    syscall

Tested on macOS 10.13.6 在macOS 10.13.6上测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM