之前的兩篇(這個和這個)組語文裡面是直接使用system call來完成我們的願望。當然,就發現新大陸(?)的角度來看,這是相當有趣的。但如果想要快一點用組合語言來放煙火,那麼直接使用現有的程式庫會比較快。
在組合語言裡面,要呼叫程式庫的功能(用稍微專業點的詞彙來表達的話,是指函數(function)),需要遵守一些既定的規則。就像是親愛的讀者,如果想要搭捷運,就必須在出捷運站以及進捷運站的時候刷卡,不然就算是犯規了。
這套規則主要在描述一個函數被呼叫的時候,必須要怎麼樣安排參數,以及哪些暫存器是可能被更改的,哪些絕對會被保留下來等等的規定。詳細的內容請參考這份文件。
接著來看程式碼吧!想編譯以下的程式碼的話,使用:
gcc put.s
.section .text /* 這次我們用像C語言一樣的作法來寫 這次的程式:使用main當作程式的起 點 */ .global main .type main, @function main: /* x86-64 ABI (user mode) 參數依照下面的順序傳遞: rdi rsi rdx rcx r8 r9 puts有一個參數:要印出資料的指標 必須以NULL結尾。 */ mov $hello_str, %rdi call puts /* rax是函數的return value 我們希望main傳回0,所以設定 rax = 0 xor %rax, %rax 效果等同於 mov $0, %rax */ xor %rax, %rax ret .section .rodata hello_str: /* .string 後面所接的字串,會由 組譯器補上'\0' (NULL) 所以,下面的字串會變成 "Hello!\0" 總之,由.string所形成的字串常數 會變成可以在C語言的世界中方便使用 的字串喔! */ .string "Hello!"
其實如果很熟x86-64 ABI的人就會發現這個程式碼應該有可以補強的地方。親愛的讀者,看得出來嗎?
沒有留言:
張貼留言