为什么 int addition though pointers 比 int multiplication through pointers 少了一条 x86 指令?
Why does int addition though pointers take one less x86 instruction than int multiplication through pointers?
我有以下 C/C++ 代码 (compiler explorer link):
void update_mul(int *x, int *amount) {
*x *= *amount;
}
void update_add(int *x, int *amount) {
*x += *amount;
}
在 clang 和 gcc 编译为 C 或 C++ 且至少启用 -O1
的情况下,以上内容转换为此程序集:
update_mul: # @update_mul
mov eax, dword ptr [rdi]
imul eax, dword ptr [rsi]
mov dword ptr [rdi], eax
ret
update_add: # @update_add
mov eax, dword ptr [rsi]
add dword ptr [rdi], eax
ret
添加它似乎在做类似的事情:
register = *amount;
*x += register;
但是对于乘法它正在做:
register = *x;
register *= *amount;
*x = register;
为什么乘法比加法需要额外的指令,或者不需要但只是更快?
IA-32 architecture specification (alternative single-page link) 显示目标(第一个参数)是内存操作数的 IMUL 根本没有编码:
Encoding | Meaning
IMUL r/m8* | AX ← AL ∗ r/m byte.
IMUL r/m16 | DX:AX ← AX ∗ r/m word.
IMUL r/m32 | EDX:EAX ← EAX ∗ r/m32.
IMUL r/m64 | RDX:RAX ← RAX ∗ r/m64.
IMUL r16, r/m16 | word register ← word register ∗ r/m16.
IMUL r32, r/m32 | doubleword register ← doubleword register ∗ r/m32.
IMUL r64, r/m64 | Quadword register ← Quadword register ∗ r/m64.
IMUL r16, r/m16, imm8 | word register ← r/m16 ∗ sign-extended immediate byte.
IMUL r32, r/m32, imm8 | doubleword register ← r/m32 ∗ sign- extended immediate byte.
IMUL r64, r/m64, imm8 | Quadword register ← r/m64 ∗ sign-extended immediate byte.
IMUL r16, r/m16, imm16 | word register ← r/m16 ∗ immediate word.
IMUL r32, r/m32, imm32 | doubleword register ← r/m32 ∗ immediate doubleword.
IMUL r64, r/m64, imm32 | Quadword register ← r/m64 ∗ immediate doubleword.
我有以下 C/C++ 代码 (compiler explorer link):
void update_mul(int *x, int *amount) {
*x *= *amount;
}
void update_add(int *x, int *amount) {
*x += *amount;
}
在 clang 和 gcc 编译为 C 或 C++ 且至少启用 -O1
的情况下,以上内容转换为此程序集:
update_mul: # @update_mul
mov eax, dword ptr [rdi]
imul eax, dword ptr [rsi]
mov dword ptr [rdi], eax
ret
update_add: # @update_add
mov eax, dword ptr [rsi]
add dword ptr [rdi], eax
ret
添加它似乎在做类似的事情:
register = *amount;
*x += register;
但是对于乘法它正在做:
register = *x;
register *= *amount;
*x = register;
为什么乘法比加法需要额外的指令,或者不需要但只是更快?
IA-32 architecture specification (alternative single-page link) 显示目标(第一个参数)是内存操作数的 IMUL 根本没有编码:
Encoding | Meaning
IMUL r/m8* | AX ← AL ∗ r/m byte.
IMUL r/m16 | DX:AX ← AX ∗ r/m word.
IMUL r/m32 | EDX:EAX ← EAX ∗ r/m32.
IMUL r/m64 | RDX:RAX ← RAX ∗ r/m64.
IMUL r16, r/m16 | word register ← word register ∗ r/m16.
IMUL r32, r/m32 | doubleword register ← doubleword register ∗ r/m32.
IMUL r64, r/m64 | Quadword register ← Quadword register ∗ r/m64.
IMUL r16, r/m16, imm8 | word register ← r/m16 ∗ sign-extended immediate byte.
IMUL r32, r/m32, imm8 | doubleword register ← r/m32 ∗ sign- extended immediate byte.
IMUL r64, r/m64, imm8 | Quadword register ← r/m64 ∗ sign-extended immediate byte.
IMUL r16, r/m16, imm16 | word register ← r/m16 ∗ immediate word.
IMUL r32, r/m32, imm32 | doubleword register ← r/m32 ∗ immediate doubleword.
IMUL r64, r/m64, imm32 | Quadword register ← r/m64 ∗ immediate doubleword.