2012年12月17日 星期一

x86-64組合語言:使用程式庫,拓展視野

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

沒有留言:

張貼留言