我正在通过MSIL并注意到有很多nop指令.MSDN文章称,如果操作码被修补,它们不采取任何操作并用于填充空间.它们在调试版本中比在发布版本中使用得更多.我知道这些语句用于汇编语言,以确保操作码适合字边界,但为什么MSIL需要它?
有时编译器生成具有奇怪的指令重复的代码,可以安全地删除.考虑以下代码:
int gcd(unsigned x, unsigned y) {
return x == 0 ? y : gcd(y % x, x);
}
Run Code Online (Sandbox Code Playgroud)
这是汇编代码(由clang 5.0生成并启用了优化):
gcd(unsigned int, unsigned int): # @gcd(unsigned int, unsigned int)
mov eax, esi
mov edx, edi
test edx, edx
je .LBB0_1
.LBB0_2: # =>This Inner Loop Header: Depth=1
mov ecx, edx
xor edx, edx
div ecx
test edx, edx
mov eax, ecx
jne .LBB0_2
mov eax, ecx
ret
.LBB0_1:
ret
Run Code Online (Sandbox Code Playgroud)
在以下代码段中:
mov eax, ecx
jne .LBB0_2
mov eax, …Run Code Online (Sandbox Code Playgroud) 如果您编译如下代码
#include <atomic>
int load(std::atomic<int> *p) {
return p->load(std::memory_order_acquire) + p->load(std::memory_order_acquire);
}
Run Code Online (Sandbox Code Playgroud)
int load(std::atomic<int> *) PROC
mov edx, DWORD PTR [rcx]
npad 1
mov eax, DWORD PTR [rcx]
npad 1
add eax, edx
ret 0
Run Code Online (Sandbox Code Playgroud)
为什么是这样?有什么办法可以避免它而不放松内存顺序(这会影响代码的正确性)?