2012年12月20日 星期四

x86-64組合語言:今年是閏年嗎?

如果不想看作文的話請點這裡

作文練習

『欸,今年是閏年嗎?』
突然間被問了這樣的問題
「我不知道耶」
閏年,就是所謂「多一天的年」。多的這個日子,可能開心,可能悲傷。我們無法預知未來,所以就把它當作是神大人賜予的,多一場大冒險吧!正式因為是一場未知的旅途,所以才會有所期待,並展開雙臂來迎接它不是嗎?
很明顯的扯遠了XD。仔細想想,但還是無法參透到底為什麼會有閏年呢...我還給老師了吧?一邊打字一邊這樣想著。
『以公曆为例,為「年」的計算基礎是回歸年,而一個回歸年大約等於365.24220日。...』維基百科如是說。
所以是小數點後面數字的總和囉?記得小學老師有說過某規則可以判斷...有了,寫在下面:

目前使用的格里曆閏年規則如下:
1.西元年份除以4可整除,为闰年。
2.西元年份除以4及100可整除,为平年。
3.西元年份除以4、100、400可整除,为閏年。
「格里?Gregorian吧?唸起來像格里?嗯是有點啦」我這麼吐槽著
另外
每逢閏年,2月份有29日,平年的2月份為28日。
難怪說2/29生日的人們四年才能過一次生日...好可憐。不過,親友們應該會替229君補救吧。
「查到規則了喔~」
『喔喔~所以2012年是閏年。謝謝啦!』
目送他離開的時候,我想到我現在正在進行的組合語言程式練習。
「這題目,或許意外的很適合呢!」

=========================
所以囉,下面這裡就是「計算今年是否為閏年」的程式。想跑跑看的話,使用

gcc leap_year.s
組譯並連結。

        .section .text
        .global main
        .type main, %function
main:
        sub $8, %rsp
        /*堆疊位址現在已經和16對齊了!*/

        mov $.Linput_msg, %rdi
        call puts
        
        mov $.Lin_format, %rdi
        mov %rsp, %rsi
        xor %rax, %rax
        call scanf
        mov (%rsp), %rax

        /*
        千萬記得div : rdx:rax / Op
        若是 rdx:rax 太大的話,就會造成rax裝不下結果
        ,並使「除以零」的錯誤被丟出來!
        */
        mov $100, %rdi
        mov %rax, %rsi
        xor %rdx, %rdx
        /*
        % 4 == 0 ?
        如果某個數字可以被4除盡,則其二進位必定是:
        ....0000
        */
        test $3, %rax
        jnz .Lnot_leap_year

        /*
        % 100 == 0?
        */
        divq %rdi
        cmp $0, %rdx
        jne .Lleap_year

        /*
        % 400 == 0?
        %rdi原本是100,那麼,100*4=400
        以二進位的角度來說,如果把整個「條碼」向右移動
        那就會有乘以2的效果
        相反的,把「條碼」左移,則是除以2
                向右  向左
        001 (1)  <=====>  010 (2)
        */
        mov %rsi, %rax
        shl $2, %rdi
        divq %rdi
        cmp $0, %rdx
        jne .Lnot_leap_year

        /*
        標籤的名稱如果以.L開頭,
        那麼這個標籤就不匯出現在組譯後的
        執行檔裡面。
        */
.Lleap_year:
        mov $.Lleap_year_fmt, %rdi
        xor %rax, %rax  
        call printf
        jmp .Lend_printer
.Lnot_leap_year:
        mov $.Lnonleap_fmt, %rdi
        xor %rax, %rax
        call printf
.Lend_printer:    
        
        xor %rax, %rax
        add $8, %rsp
        ret

        .section .rodata
.Lin_format:
        .string "%u"
.Linput_msg:
        .string "Please input the year."
.Lleap_year_fmt:
        .string "Year %u is a leap year.\n"
.Lnonleap_fmt:
        .string "Year %u is not a leap year.\n"
        .end
        

沒有留言:

張貼留言