如何使用 printf 为 64 位 Mac OS X 编写汇编语言 hello world 程序? [英] How to write assembly language hello world program for 64 bit Mac OS X using printf?

查看:34
本文介绍了如何使用 printf 为 64 位 Mac OS X 编写汇编语言 hello world 程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习为 64 位 Mac OS 编写汇编语言.我对 32 位 Mac OS 以及 32 位和 64 位 Linux 都没有问题.

I am trying to learn writing assembly language for 64 bit Mac OS. I have no problem with 32 bit Mac OS and both 32 bit and 64 bit Linux.

但是,Mac OS 64 位不同,我无法弄清楚.所以我是来寻求帮助的.

However, Mac OS 64 bit is different and I couldn't figure out. Therefore I am here to ask for help.

我使用系统调用打印没有问题.但是,我想学习如何使用 Mac OS 的 64 位汇编语言调用 C 函数.

I have not problem using system call to print. However, I would like to learn how to call C functions using 64 bit assembly language of Mac OS.

请看下面的代码

.data
_hello:
    .asciz "Hello, world
"


.text
.globl _main
_main:
    movq $0, %rax
    movq _hello(%rip), %rdi
    call _printf

我用$ gcc -arch x86_64 hello.s

I use $ gcc -arch x86_64 hello.s

组装和链接.

它生成二进制代码.但是,我在运行时遇到了分段错误.

It generates binary code. However, I got a segmentation fault when running it.

我尝试在调用_printf之前添加subq $8, %rsp",结果还是和之前一样.

I tried adding "subq $8, %rsp" before calling _printf, still the same result as before.

我做错了什么?

顺便说一下,有没有办法在 Mac 上调试这段代码?我尝试添加 -ggdb 或 -gstab 或 -gDWARF,然后$gdb ./a.out,看不到代码和设置断点.

By the way, is that any way to debug this code on Mac? I tried adding -ggdb or -gstab or -gDWARF, and $gdb ./a.out, and can't see the code and set break points.

推荐答案

您没有确切说明您看到的问题是什么,但我猜您在调用 <代码>printf.这是因为 OS X(32 位和 64 位)要求堆栈指针在任何外部函数调用点都具有 16 字节对齐.

You didn't say exactly what the problem you're seeing is, but I'm guessing that you're crashing at the point of the call to printf. This is because OS X (both 32- and 64-bit) requires that the stack pointer have 16-byte alignment at the point of any external function call.

调用_main时栈指针是16字节对齐的;该调用将一个 8 字节的返回地址压入堆栈,因此在调用 _printf 时堆栈不是 16 字节对齐的.在调用之前从 %rsp 中减去 8,以便正确对齐.

The stack pointer was 16-byte aligned when _main was called; that call pushed an eight-byte return address onto the stack, so the stack is not 16-byte aligned at the point of the call to _printf. Subtract eight from %rsp before making the call in order to properly align it.

所以我继续为您调试(不涉及魔法,只需使用 gdb、break maindisplay/5i $pcstepi等).您遇到的另一个问题是:

So I went ahead and debugged this for you (no magic involved, just use gdb, break main, display/5i $pc, stepi, etc). The other problem you're having is here:

movq _hello(%rip), %rdi

这将您的字符串的前八个字节加载到 %rdi 中,这根本不是您想要的(特别是,您的字符串的前八个字节极不可能构成有效的指向格式字符串的指针,这会导致 printf 崩溃).相反,您想要加载字符串的地址.您程序的调试版本是:

This loads the first eight bytes of your string into %rdi, which isn't what you want at all (in particular, the first eight bytes of your string are exceedingly unlikely to constitute a valid pointer to a format string, which results in a crash in printf). Instead, you want to load the address of the string. A debugged version of your program is:

.cstring
_hello: .asciz "Hello, world
"

.text
.globl _main
_main:
    sub  $8, %rsp           // align rsp to 16B boundary
    mov  $0, %rax
    lea  _hello(%rip), %rdi // load address of format string
    call _printf            // call printf
    add  $8, %rsp           // restore rsp
    ret

这篇关于如何使用 printf 为 64 位 Mac OS X 编写汇编语言 hello world 程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆