之前的兩篇(這個和這個)組語文裡面是直接使用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的人就會發現這個程式碼應該有可以補強的地方。親愛的讀者,看得出來嗎?
沒有留言:
張貼留言