【发布时间】:2022-01-19 05:11:40
【问题描述】:
我有以下代码:
#include <x86intrin.h>
int main() {
return __rdtsc();
}
我尝试在我的机器(Intel i7-6700 CPU)和objdump上编译
g++ -Wall test_tsc.cpp -o test_tsc -march=native -mtune=native -O0 -std=c++20
objdump -M intel -d test_tsc > test_tsc.O0
然后在test_tsc.O0:
0000000000401122 <main>:
401122: 55 push rbp
401123: 48 89 e5 mov rbp,rsp
401126: 0f 31 rdtsc
401128: 48 c1 e2 20 shl rdx,0x20
40112c: 48 09 d0 or rax,rdx
40112f: 90 nop
401130: 5d pop rbp
401131: c3 ret
401132: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
401139: 00 00 00
40113c: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
push rbp 和 mov rbp,rsp 做什么?似乎它们是为了保存堆栈指针,但实际上并没有函数调用。如果g++认为__rdtsc()是一个函数调用,那么后面还会有call这样的东西吗?
谢谢。
【问题讨论】:
-
由于各种原因,函数prologue/epilogue经常被无条件发出。
-
用 -O2 编译它,你会得到 rdst 后跟 ret (这是你所期望的)。如果您编译非优化调试版本(就像您在此处所做的那样),编译器将通过将寄存器值复制到已知内存位置(然后调试器能够轻松访问)来“优化”代码。结果是一堆毫无意义的mov。只需使用 -O2 或 -O3。
-
因为你使用了
-O0,当然-fno-omit-frame-pointer是默认的。 RBP 帧指针设置/拆卸即使在空函数中也会发生(与叶函数可能仍忽略帧指针的 clang 不同)。 godbolt.org/z/cEPGssYac。这不是“用于保存堆栈指针”,您无法有效地保存/恢复堆栈上的堆栈指针。