1. 程式人生 > >C IN ARM64 彙編基礎-變數與表示式-基於The C Programming Language - Second Edition

C IN ARM64 彙編基礎-變數與表示式-基於The C Programming Language - Second Edition

C原始碼:

#include <stdio.h>

/* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300 */ 
main() {
    int fahr, celsius;
    int lower, upper, step;

    lower = 0;    /* lower limit of temperature scale */
    upper = 300;  /* upper limit */
    step = 20;     /* step size */

    fahr = lower;
    while (fahr <= upper) {
        celsius = 5 * (fahr-32) / 9;
        printf("%d\t%d\n", fahr, celsius);
        fahr = fahr + step;
    }
}

對應彙編程式碼:

00000000000005b0 <main>:
 5b0:   a9bd57f6    stp x22, x21, [sp,#-48]! //申請48bytes的棧空間,sp = sp - 48,stp指令為儲存一對資料,依次儲存x22、x21到sp-48處
 5b4:   a9014ff4    stp x20, x19, [sp,#16]   //sp+16的位置儲存x20、x19
 5b8:   a9027bfd    stp x29, x30, [sp,#32]   //sp+32的位置儲存x29、x30
 5bc:   910083fd    add x29, sp, #0x20       //x29,也就是fp指向sp+32
 5c0:   52a71c76    mov w22, #0x38e30000   // #954400768//w22儲存#0x38e30000,4個byte
 5c4:   90000014    adrp    x20, 0 <abitag-0x200>
 5c8:   2a1f03f3    mov w19, wzr           //w19儲存0暫存器的值0
 5cc:   128013f5    mov w21, #0xffffff60                // #-160
 5d0:   7291c736    movk    w22, #0x8e39
 5d4:   91186294    add x20, x20, #0x618
 5d8:   9b367ea8    smull   x8, w21, w22   //smull為64位乘法指令
 5dc:   d37ffd09    lsr x9, x8, #63   
 5e0:   9361fd08    asr x8, x8, #33
 5e4:   0b090102    add w2, w8, w9
 5e8:   aa1403e0    mov x0, x20
 5ec:   2a1303e1    mov w1, w19
 5f0:   97ffffc0    bl  4f0 <
[email protected]
> //跳轉到print函式 5f4: 11005273 add w19, w19, #0x14 //w19暫存器中的內容加0x14 5f8: 110192b5 add w21, w21, #0x64 5fc: 7104b67f cmp w19, #0x12d //將w19暫存器中的值與0x12d進行比較 600: 54fffecb b.lt 5d8 <main+0x28> //小於的話跳轉到5d8 604: a9427bfd ldp x29, x30, [sp,#32] 608: a9414ff4 ldp x20, x19, [sp,#16] 60c: 2a1f03e0 mov w0, wzr 610: a8c357f6 ldp x22, x21, [sp],#48 614: d65f03c0 ret

彙編中全程未看見變數與常量的值都在哪,看起來有點懵,這種可以找一下關鍵點。

關鍵點如下:

首先有個while迴圈,fahr <= upper成立時跳轉到5d8,5d8處是乘法指令,是在執行celsius = 5 * (fahr-32) / 9計算。所以開始處的暫存器x21、x22是儲存乘法運算用到的臨時變數的,對x21、x22的操作是如何對應到celsius = 5 * (fahr-32) / 9的,這裡就不詳細分析了,涉及到的細節比較多。

上面的彙編原始碼是優化後的,一般預設的情況下都是有優化的,我們在解native問題時拿到的symbols也是優化過的,有了編譯優化會增加問題的分析難度。下面是未優化過的彙編原始碼,與C原始碼是高度吻合的,也很好分析。

00000000000005b0 <main>:
 5b0:   d100c3ff    sub sp, sp, #0x30
 5b4:   a9027bfd    stp x29, x30, [sp,#32]
 5b8:   910083fd    add x29, sp, #0x20
 5bc:   52800288    mov w8, #0x14                   // #20
 5c0:   52802589    mov w9, #0x12c                  // #300
 5c4:   b81fc3bf    stur    wzr, [x29,#-4]
 5c8:   b90013ff    str wzr, [sp,#16]
 5cc:   b9000fe9    str w9, [sp,#12]
 5d0:   b9000be8    str w8, [sp,#8]
 5d4:   b94013e8    ldr w8, [sp,#16]
 5d8:   b81f83a8    stur    w8, [x29,#-8]
 5dc:   b85f83a8    ldur    w8, [x29,#-8]
 5e0:   b9400fe9    ldr w9, [sp,#12]
 5e4:   6b09011f    cmp w8, w9
 5e8:   5400026c    b.gt    634 <main+0x84>
 5ec:   528000a8    mov w8, #0x5                    // #5
 5f0:   b85f83a9    ldur    w9, [x29,#-8]
 5f4:   51008129    sub w9, w9, #0x20
 5f8:   1b097d08    mul w8, w8, w9
 5fc:   52800129    mov w9, #0x9                    // #9
 600:   1ac90d08    sdiv    w8, w8, w9
 604:   b81f43a8    stur    w8, [x29,#-12]
 608:   b85f83a1    ldur    w1, [x29,#-8]
 60c:   b85f43a2    ldur    w2, [x29,#-12]
 610:   90000000    adrp    x0, 0 <abitag-0x200>
 614:   91191000    add x0, x0, #0x644
 618:   97ffffb6    bl  4f0 <[email protected]>
 61c:   b85f83a8    ldur    w8, [x29,#-8]
 620:   b9400be9    ldr w9, [sp,#8]
 624:   0b090108    add w8, w8, w9
 628:   b81f83a8    stur    w8, [x29,#-8]
 62c:   b90007e0    str w0, [sp,#4]
 630:   17ffffeb    b   5dc <main+0x2c>
 634:   b85fc3a0    ldur    w0, [x29,#-4]
 638:   a9427bfd    ldp x29, x30, [sp,#32]
 63c:   9100c3ff    add sp, sp, #0x30
 640:   d65f03c0    ret