当前位置: 首页 > 知识库问答 >
问题:

为什么通过指针进行的整数加法比通过指针进行的整数乘法少使用一条x86指令?

段干帅
2023-03-14

我有以下C/C代码(编译器浏览器链接):

void update_mul(int *x, int *amount) { 
    *x *= *amount; 
}

void update_add(int *x, int *amount) { 
    *x += *amount; 
}

在clang和gcc编译为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

对于add,它似乎在做一些类似于:

register = *amount;
*x += register;

但是对于乘法,它正在做:

register = *x;
register *= *amount;
*x = register;

为什么乘法在加法上需要额外的指令,或者它不是必需的,只是更快?

共有1个答案

高宏峻
2023-03-14

IA-32体系结构规范(替代单页链接)表明,在目标(第一个参数)是内存操作数的情况下,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.

 类似资料:
  • 违反严格别名规则会产生未定义的行为,例如,当通过网络将结构发送到char缓冲区时,然后该char指针被C-style/< code > STD::reinterpret _ cast()强制转换为结构指针。 C函数看起来可以用于以(实现?)定义的方式转换此类指针,即不违反严格的混淆现象规则。 示例: 因此,的调用方以某种方式获得了一个指针,并确定它实际上指向一个struct。 那么,通过 进行此类

  • 我在Rust中尝试函数指针魔术,最后得到了一个代码片段,我完全无法解释它为什么要编译,甚至无法解释它为什么要运行。 我无法解释为什么调用的方法是在

  • 我想知道实际上是如何工作的。我认为这是一种计算数组长度的简单方法,并希望在使用它之前适当地理解它。我对指针算术不是很有经验,但根据我的理解,给出了数组第一个元素的地址。将按地址转到数组的末尾。但是不应该给出这个地址的值吗。而是打印出地址。我真的很感激你帮我把指针的东西弄清楚。 下面是我正在研究的一个简单示例:

  • 本文向大家介绍什么是指向指针的指针? 相关面试题,主要包含被问及什么是指向指针的指针? 时的应答技巧和注意事项,需要的朋友参考一下 指针指向的变量是一个指针,即具体内容为一个指针的值,是一个地址. 此时指针指向的变量长度也是4位.

  • 6. 指向指针的指针与指针数组 指针可以指向基本类型,也可以指向复合类型,因此也可以指向另外一个指针变量,称为指向指针的指针。 int i; int *pi = &i; int **ppi = &pi; 这样定义之后,表达式*ppi取pi的值,表达式**ppi取i的值。请读者自己画图理解i、pi、ppi这三个变量之间的关系。 很自然地,也可以定义指向“指向指针的指针”的指针,但是很少用到: int

  • 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个 指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是 函数指针。 函数指针的定义形式为: returnType (*pointerName)(param list); returnType