2012年12月25日 星期二

x86-64組合語言:這個圓多大?

首先祝各位親愛的讀者聖誕節快樂喔!這次的主題是組合語言中小數的操作。感覺起來很無聊?沒錯啦,這主題本身連我聽起來連我都覺得有些無聊。但我還是想要把它貼出來,因為呢,藏在主題下面的東西其實有些小故事可以說。也就是,本文的程式碼是講無趣小故事的藉口。

親愛的讀者,如果之前學習過,或者是欣賞過32位元x86組合語言程式的話(附帶一提,那裡的呼叫協定真的是一團糟),可能就知道在該平台上計算小數的主流是x87 fpu指令。x87 fpu指令可以做純量的數學計算,並且配有80-bit浮點數的計算能力。然而,因為x87暫存器設計的關係,個人覺得該指令使用的難度比較高,用起來比較有被綁手的感覺。

而現在,具有x86-64處理器的cpu具有SSE指令。這套指令裡面就配有小數純量處理的指令,暫存器的使用卻更加的有彈性,用起來也比較開心。於是,在大部份的狀況下,小數的計算利用SSE指令完成,而參數的傳遞,和x64 ABI所說的一樣,也是利用SSE的暫存器(xmm暫存器)來傳遞。

還先不用替x87 fpu掉眼淚。x87指令相對於SSE還是有不可取代的優勢。有些數學函數,像是sin, cos等,如果想要靠硬體來完成,那只能求x87 fpu了。讓x87得以保留飯碗的另一個因素是80-bit浮點數計算能力。總之x87在這幾年應該不會失業,請各位放心 ^_^

剩下的呢,請各位親愛的讀者欣賞一下簡單的程式小品囉。

        .section .text
        .global main
        .type main, %function
main:
        /*堆疊指標向16位元組對齊*/
        sub $8, %rsp

        /*計算圓面積*/
        movsd .Lr, %xmm0
        movsd %xmm0, %xmm2
        movsd .Lpi, %xmm1
        mulsd %xmm0, %xmm0
        mulsd %xmm1, %xmm0

        mov $.Lfmt, %rdi
        /*rax表示會使用到的xmm暫存器數量*/
        mov $2, %rax
        /*浮點參數依照xmm0, xmm1 ..的順序傳遞*/
        movsd %xmm0, %xmm1
        movsd %xmm2, %xmm0
        call printf

        xor %rax, %rax
        add $8, %rsp
        ret
        
        .section .rodata
.Lr:
        .double 5.0
.Lpi:
        .double 3.14159
.Lfmt:
        .string "The area of radius %f is %f\n"
        .end

沒有留言:

張貼留言