[实验]-从汇编代码来看volatile关键字的作用

★★★ 个人博客导读首页—点击此处 ★★★

环境aarch64的交叉编译器
我们将C语言翻译成汇编代码,来看volatile关键字的作用

我们先看一段C语言代码

void udelay(uint64_t usec)
{
        uint64_t start, cnt, delta,freq;
        volatile uint64_t delta_us = 0;  //------------------在这里定义了一个volatile变量
        uint64_t reference_ratio = 16;

        if(timer_start == 0)
        {
                generic_timer_start();
                start = read_cntpct_el0();
                delta_us = 1000;  //------------------ 给这个变量赋值100
                while(delta_us) //------------------ 使用这个变量,这里是判断该变量是否等于0,然后走相应逻辑
                {
                        cnt = read_cntpct_el0();
                        if(cnt != start)
                                break;
                        delta_us--;
                        if(delta_us == 0)
                        {
                                base_frequency = 0;
                        }
                }
                INFO("base_frequency %ld\n",base_frequency);
        }
......
}

翻译成汇编后,从汇编代码来看,delta_us=1000,直接将1000写道栈尾中了.
while(delta_us)代码,需要读出delta_us,也是种栈尾种读出来的

00000000002034b4 <udelay>:
  2034b4:       a9bd7bfd        stp     x29, x30, [sp,#-48]!
  2034b8:       910003fd        mov     x29, sp
  2034bc:       a90153f3        stp     x19, x20, [sp,#16]
  2034c0:       aa0003f3        mov     x19, x0
  2034c4:       b00000c0        adrp    x0, 21c000 <xxx_middle_mem_pool+0xa40>
  2034c8:       f90017bf        str     xzr, [x29,#40]
  2034cc:       900000d4        adrp    x20, 21b000 <buf+0xdb8>
  2034d0:       b94f9c00        ldr     w0, [x0,#3996]
  2034d4:       340000a0        cbz     w0, 2034e8 <udelay+0x34>
  2034d8:       f9412a80        ldr     x0, [x20,#592]
  2034dc:       b50003a0        cbnz    x0, 203550 <udelay+0x9c>
  2034e0:       d37cee73        lsl     x19, x19, #4
  2034e4:       14000014        b       203534 <udelay+0x80>
  2034e8:       97ffffdd        bl      20345c <generic_timer_start>
  2034ec:       d53be022        mrs     x2, cntpct_el0
  2034f0:       d2807d00        mov     x0, #0x3e8  //------------------------ 0x3e8-#1000给x0赋值1000,x0就表示delta_us变量
  2034f4:       f90017a0        str     x0, [x29,#40] //------------------------ 将这个变量写到栈尾内存(其实可能是main-memory,也可能写入到了cache中)
  2034f8:       f9412a80        ldr     x0, [x20,#592]
  2034fc:       f94017a1        ldr     x1, [x29,#40] //------------------------ 将这个变量从栈尾内存读出来,放到X1中
  203500:       b4000161        cbz     x1, 20352c <udelay+0x78> //------------------------ 比较x1是否等于0,然后走相应的分支
  203504:       d53be021        mrs     x1, cntpct_el0
  203508:       eb02003f        cmp     x1, x2
  20350c:       54000101        b.ne    20352c <udelay+0x78>
  203510:       f94017a1        ldr     x1, [x29,#40]  //----------------------- 在操作(delta_us--)时,再次从内存中去读
  203514:       d1000421        sub     x1, x1, #0x1   // 这样对应 delta_us--
  203518:       f90017a1        str     x1, [x29,#40]
  20351c:       f94017a1        ldr     x1, [x29,#40]
  203520:       eb1f003f        cmp     x1, xzr
  203524:       9a9f1000        csel    x0, x0, xzr, ne

我们去除volatile关键字后,再翻译成汇编:
uint64_t delta_us = 0; //------------------在这里定义了一个volatile变量
翻译成汇编后,从汇编代码来看,delta_us=1000,只是将1000写入到了x0寄存器中

0000000002034b4 <udelay>:
  2034b4:       a9be7bfd        stp     x29, x30, [sp,#-32]!
  2034b8:       910003fd        mov     x29, sp
  2034bc:       f9000bf3        str     x19, [sp,#16]
  2034c0:       aa0003f3        mov     x19, x0
  2034c4:       b00000c0        adrp    x0, 21c000 <xxx_middle_mem_pool+0xa40>
  2034c8:       b94f9c00        ldr     w0, [x0,#3996]
  2034cc:       35000160        cbnz    w0, 2034f8 <udelay+0x44>
  2034d0:       97ffffe3        bl      20345c <generic_timer_start>
  2034d4:       d53be021        mrs     x1, cntpct_el0
  2034d8:       d2807d00        mov     x0, #0x3e8  //------------------------ 0x3e8-#1000给x0赋值100,x0就表示delta_us变量
  2034dc:       d53be022        mrs     x2, cntpct_el0
  2034e0:       eb01005f        cmp     x2, x1
  2034e4:       540000a1        b.ne    2034f8 <udelay+0x44>
  2034e8:       f1000400        subs    x0, x0, #0x1   //------------------ 这行对应的delta_us--
  2034ec:       54ffff81        b.ne    2034dc <udelay+0x28>
  2034f0:       900000c0        adrp    x0, 21b000 <buf+0xdb8>
  2034f4:       f901281f        str     xzr, [x0,#592]
  2034f8:       900000c0        adrp    x0, 21b000 <buf+0xdb8>
  2034fc:       f9412801        ldr     x1, [x0,#592]

总结volatile关键字的作用:其实就算告诉编译器,我要读写的数据,不要从X0-X30通用寄存器中读取,每次都要从内存中去读取,这里说的内存可能是主内存(main-memory)、也可能是各级cache等

上一篇:DestinationRule


下一篇:Win10企业版激活