2012-01-01 31 views
13

我想學習爲64位Mac OS編寫彙編語言。我對32位Mac OS以及32位和64位Linux都沒有問題。如何使用printf編寫用於64位Mac OS X的彙編語言hello world程序?

但是,Mac OS 64位是不同的,我無法弄清楚。因此我在這裏尋求幫助。

我沒有問題使用系統調用來打印。但是,我想學習如何使用64位Mac OS彙編語言調用C函數。

請看下面的代碼

.data 
_hello: 
    .asciz "Hello, world\n" 


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

我用 $ GCC -arch x86_64的hello.s

組裝和鏈接。

它生成二進制代碼。但是,運行時出現分段錯誤。

我試着在調用_printf之前添加「subq $ 8,%rsp」,仍然和以前一樣。

我做錯了什麼?

順便說一句,任何方式來在Mac上調試此代碼?我嘗試添加-ggdb或-gstab或-gDWARF,並且$ gdb ./a.out,並且不能看到代碼並設置斷點。

+1

在x86_64的調用約定好文章:http://nickdesaulniers.github.io/blog/2014/04/18/lets-write-some-x86-64/ – 2015-07-08 14:34:28

+0

eax for vararg count:http://stackoverflow.com/questions/6212665,對齊問題:http://stackoverflow.com/questions/10324333,http://stackoverflow.com/questions/14000351,通用問題:http:/ /stackoverflow.com/questions/10857273 – 2015-07-08 15:01:47

回答

8

你沒有確切地說出你所看到的問題是什麼,但是我猜測你在致電printf時會崩潰。這是因爲OS X(32位和64位)要求堆棧指針在任何外部函數調用時都有16字節對齊。

當調用_main時,堆棧指針是16字節對齊的;該調用將一個八字節的返回地址壓入堆棧,所以堆棧在調用_printf時不會與16字節對齊。在撥打電話之前從%rsp減去8,以便正確對齊。


所以我繼續和調試這件事情(沒有魔法參與,只需使用GDB,break maindisplay/5i $pcstepi等)。您遇到的另一個問題是在這裏:

movq _hello(%rip), %rdi 

這會將前八個字節您的字符串到%rdi,這是不是你想要的所有(特別是前八個字節您的字符串是極不可能構成格式字符串的有效指針,導致在printf中發生崩潰)。相反,您要加載字符串的地址。你的程序的調試版本是:

.cstring 
_hello: .asciz "Hello, world\n" 

.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 
+0

謝謝,斯蒂芬。我知道16字節的堆棧對齊問題。我添加了subq $ 8,%rsp並仍然出現分段錯誤...我懷疑movq _hello(%rip),%rdi,我不確定這是否正確。在Linux上,我只能使用movq _hello,%rdi,但是mac會抱怨絕對地址不受支持。 – 2012-01-01 17:41:43

+0

@AlfredZhong:爲你更新了我的答案。 – 2012-01-01 18:47:36

+0

再次感謝斯蒂芬!有用!多麼神奇!我其實嘗試過使用leaq。但是,我沒有意識到即使沒有在堆棧上推送任何參數,堆棧仍然必須以16字節對齊。多麼令人困惑的情況! – 2012-01-03 07:08:26

相關問題