- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编译了以下程序:
#include <stdint.h>
uint64_t usquare(uint32_t x) {
return (uint64_t)x * (uint64_t)x;
}
0: 89 f8 mov eax,edi
2: 48 0f af c0 imul rax,rax
6: c3 ret
imul
是乘法指令
签名 数字。为什么它被
gcc
使用然后?
uint64_t
时 assembly 是类似的:
0: 48 0f af ff imul rdi,rdi
4: 48 89 f8 mov rax,rdi
7: c3 ret
最佳答案
TL:DR:因为当我们不关心上半部分(即输出仅与 2 个输入一样宽)时,这是获得正确结果的更快方法。更灵活的寄存器分配,而不是强制使用 RAX 和 RDX。
如果它不能用于此,英特尔可能会添加 mul
的两个操作数版本。以及。但这不是必需的,正如这个答案所解释的那样。
WARNING This answer is long!
... and it's full of unneeded explanations - but I have always wanted to write something more lengthy about the multiplication.
imul
的两种形式
imul
有两种形式:完整形式和部分形式。
imul ax ;16x16->32, Result is dx:ax
imul rax ;64x64->128, Result is rdx:rax
imul ax, ax ;16x16->16, Lower WORD of the result is ax
imul rax, rax ;64x64->64, Lower QWORD of the result is rax
imul r64, r/m64, imm8/32
,它允许您在一条指令中复制并乘以一个常量。它没有隐式操作数,并且同样不会在任何地方写入高半,所以我们可以处理它等同于
imul r64, r/m64
dst *= src
形式。)
imul
对比
mul
imul
的区别和
mul
在于操作数的转换方式。
mul
指令只是用零填充上部 - 它零扩展。
imul
指令复制高位(左起第一个) - 这称为符号扩展,它具有转换
two's complement 的有趣特性。将 n 位的有符号数转换为具有相同符号和模数的 2 n 位有符号数(即它做正确的事情,留给读者找到零扩展情况的反例)。
How mul extends How imul extends
and operand and operand
+----+ +----+ +----+ +----+
|0...| |1...| |0...| |1...|
+----+ +----+ +----+ +----+
+----+----+ +----+----+ +----+----+ +----+----+
|0000|0...| |0000|1...| |0000|0...| |1111|1...|
+----+----+ +----+----+ +----+----+ +----+----+
imul
的区别和
mul
仅从第 (n+1) 位开始可见。
imul
的部分形式的结果与
mul
相同.
imul
退出?
mul
的单操作数版本和
imul
. x86 的更高版本添加了更灵活的二和三操作数版本
imul
仅适用于您不想要双宽结果的常见用例。
imul r32
在英特尔 CPU 上是 3 个 uops:大概是一个乘法,另一个将 64 位产品分成两半并写入低半部分,另一个对高半部分做同样的事情。
imul r64
是 2 uop;大概 128 位结果来自已经分成 64 位一半的乘法器。
mul
仍然只以非常古老的单操作数形式存在,固定寄存器作为接口(interface)的一部分。
imul
根据有符号乘法设置标志 - 如果部分结果丢弃了任何重要信息(技术条件是:部分结果的符号扩展与完整结果不同),则设置 CF 和 OF,例如在溢出的情况下。
mul
的原因。 ,否则这将是一个非常合适的名称。
#include <stdint.h>
uint64_t foo(uint32_t a)
{
return a*(uint64_t)a;
}
imul
因为一个
unint64_t
适合一个寄存器,因此 64×64→64 乘法可用作
imul <reg64>, <reg64>
foo(unsigned int):
mov eax, edi ;edi = a
imul rax, rax ;64x64->64
ret
imul
的这种乘法。 .
imul <reg32>
或
imul <reg32>, <reg32>, <reg32>
是必要的,但这会产生完整的结果!并且完整的有符号结果通常不等于完整的无符号结果。
mul
:
foo(unsigned int):
mov eax, DWORD PTR [esp+4]
mul eax
ret
You probably means that this is only a way of thinking about it, conceptually. The processor does not necessarily do a full 128-bit multiplication when you use the 64x64 -> 64 form. Indeed, the truncated form takes only 1 uop on recent Intel, but the full form takes 2 uops, so some extra work is being done
Similarly the sign extension may happens "conceptually", but probably not in hardware. They won't have the extra wires and transistors just to do the sign or zero extension, which would add a lot of bulk to an already huge multiplier, but will use some other tricks to do the multiplication "as if" that had happened.
关于assembly - 为什么 imul 用于乘以无符号数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42587607/
谢谢帮助,我的问题是关于从下面的代码中收到的 ax 值? mov al,22h mov cl,0fdh imul cl 真机结果:ff9a 我的预期:00:9a(通过二进制相乘) 第一个数字是 22h
我编译了以下程序: #include uint64_t usquare(uint32_t x) { return (uint64_t)x * (uint64_t)x; } 这反汇编为: 0:
我正在使用运行时调试器。 EAX:0000 0023 EDX:5555 5556 imul edx EAX:aaaa aac2 EDX:0000 000b 我完全困惑,无法弄清楚这种乘法是如何工作的。
我目前正在从游戏中反转哈希函数并遇到了这个问题: Game.exe+1F745D - 69 C0 93 01 00 01 - imul eax,eax,Game.exe+C00193 指令本身不是问题
哪个更快 - val = val*10; 或 val = (val<<3) + (val<<2); 与移位指令相比,imul 需要多少个时钟周期? 最佳答案 这是21世纪。现代硬件和编译器知道如何生成
我正在学习 ASM 语言并在 Ubuntu Eclipse C++ 上试用 IMUL 函数,但出于某种原因,我似乎无法从我的代码中获得所需的输出。 Required: Multiply the neg
它比 * 表达式表现更好吗?为什么? This article描述它对像 Emscripten 这样的项目很有用。这是为什么? 谢谢 最佳答案 精简版 Math.imul(a,b) 将 a 和 b 相
我必须用 C 语言编写什么才能让汇编器用一个操作数显示 imul ?例如: imul %ebp 最佳答案 如果您想编写 C 代码,以便编译器使用一个操作数发出 imul,那么唯一的方法是使用加宽有符
我写了一个非常基本的 C 函数,叫做“multby22”,它的作用正如它的名字所暗示的那样:它需要一个 long 并返回那个 long 乘以 22。(我知道这是一个毫无意义的函数,但我把它写到尝试帮助
我发现 mul和 imul可用于将有符号数乘以无符号数。 例如: global _start section .data byteVariable DB -5 section .text _s
所以,我有这样的代码: XOR DX, DX MOV BX, 1 MOV AX, BX MOV CX, 10 .LOOP: JCXZ .EXIT_LOOP
我想知道,主要是出于好奇,对于一个操作使用同一个寄存器是否比使用两个更好。考虑到性能和/或其他问题,什么会更好? mov %rbx, %rcx imul %rcx, %rcx 或者 mov %rbx,
MUL 运算符只有单操作数形式有什么原因吗? IMUL 运算符可以采用三种不同的形式(一个、两个或三个操作数),这样更方便。从技术的角度来看,我看不出 MUL 运算符不能采用二/三操作数形式的任何原因
我在尝试使用 Math.imul() 方法,我发现它在输入很少时速度更快,而在输入很多时速度较慢。这是为什么? (也许它与 Math.imul() 本身无关,但这没关系,我仍然有兴趣了解我得到的结果!
这个问题是关于我们如何将一个整数与一个常数相乘。那么让我们看一个简单的函数: int f(int x) { return 10*x; } 如何才能最好地优化该函数,尤其是在内联到调用方时? 方
在/O2(发行版)模式下查看Visual Studio(2015U2)生成的程序集时,我看到此“手动优化”的C代码片段已转换回乘法: int64_t calc(int64_t a) { retur
我正在阅读说明 imul 0xffffffd4(%ebp, %ebx, 4), %eax 我对它到底在做什么感到困惑。我知道 imul 相乘,但我无法弄清楚语法。 最佳答案 (我知道并且更喜欢 Int
我正在查看为这个简单的 x64 程序生成的程序集 Visual Studio: struct Point { int a, b; Point() { a = 0; b
说我有 EDX = 0xA28 EAX = 0x0A280105 我运行这段 ASM 代码 IMUL EDX 据我所知,如果指定了一个操作数,它只使用 EAX.. 所以在C代码中应该是这样的 EAX
我试图从本质上得到以下结果...... Inputs EAX, EDX IMUL EDX Return EAX:EDX as full 64-bit result 我正在查看 https://gito
我是一名优秀的程序员,十分优秀!