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 <printf@plt>   //跳转到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 <printf@plt>
 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

猜你喜欢

转载自blog.csdn.net/EMH1899/article/details/83112973