x64汇编学习(2)-- volatile

Last Updated: 2023-10-02 14:19:01 Monday

-- TOC --

通过汇编代码,看看volatile变量的真实面目,测试用C代码如下:

#include <stdio.h>

int f(){
    volatile int a = 1;
    int b = a;
    int c = a;
    return a;
}

int main(){
    f();
    return 0;
}

-O0

不开优化,汇编如下:

f():
        push    rbp  # 
        mov     rbp, rsp
        mov     DWORD PTR [rbp-12], 1
        mov     eax, DWORD PTR [rbp-12]
        mov     DWORD PTR [rbp-4], eax
        mov     eax, DWORD PTR [rbp-12]
        mov     DWORD PTR [rbp-8], eax
        mov     eax, DWORD PTR [rbp-12]
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        call    f()
        mov     eax, 0
        pop     rbp
        ret

标准的prologue和epilogue,用寄存器中转变量值。如果将C代码中的volatile去掉,汇编不变。

-O1

f():
        mov     DWORD PTR [rsp-4], 1
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        ret
main:
        call    f()  # 有个push操作
        mov     eax, 0
        ret

因为a被申明为volatile,因此,每次对a的访问,都是访问内存。如果去掉volatile,汇编会优化得比C代码还简单:

f():
        mov     eax, 1
        ret
main:
        mov     eax, 0
        ret

-O3

在-O3下,默认inline了:

f():
        mov     DWORD PTR [rsp-4], 1
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        ret
main:
        mov     DWORD PTR [rsp-4], 1
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        mov     eax, DWORD PTR [rsp-4]
        xor     eax, eax
        ret

去掉volatile后:

f():
        mov     eax, 1
        ret
main:
        xor     eax, eax  # rax=0
        ret

volatile到底是啥?

就是强制通过内存来得到变量的值!

在嵌入式开发中,有些内存区域会被代码以外的其它因素影响,因此读取这些变量,一定要访问内存。

用xor置零

并不是因为xor比mov快,而是xor指令更短,可以节省字节数。

不过,xor会改变flags,mov不会!

xor reg, reg所有CPU的最佳选择,没有其他方法比它有任何优势,它至少比任何其他方法都有一些优势。它是由英特尔和AMD正式推荐的。

在64位模式下,仍然使用xor r32, r32,因为写32位寄存器会将高32位也置零。xor r64,r64会浪费一个字节,因为它需要一个REX前缀。

x64规定操作64位寄存器的指令,必须要带上1byte的REX前缀,作为指令标识。

还有些其它好处...比如对某些CPU,节省功耗。

本文链接:https://cs.pynote.net/hd/asm/202302092/

-- EOF --

-- MORE --