我正在尝试在汇编中执行简单的乘法运算。然而,当调用MUL
函数时,我并没有看到寄存器发生变化。
mov bx, 5
mov cx, 10
mul cx
我正在尝试在汇编中执行简单的乘法运算。然而,当调用MUL
函数时,我并没有看到寄存器发生变化。
mov bx, 5
mov cx, 10
mul cx
mov ax, 5 ; ax = 5
mov cx, 10 ; cx = 10
mul cx ; ax = ax * cx ; actually dx:ax = ax * cx
结果将存储在隐含目标寄存器ax
中。dx:ax
中。这是一个寄存器对,意味着结果的高位部分将存储在dx
中,而低位部分将存储在ax
中。为什么会有这种额外的复杂性?因为两个16位值的乘积可能会导致一个大于16位的值!以一对16位寄存器的形式返回完整的乘积结果允许mul
指令返回32位结果。不过当你刚开始学习时,你不需要担心这个。你可以忽略溢出的可能性,并从ax
中提取结果的低位部分。(但请记住,16位mul
会覆盖dx
,无论你是否想要。在386和更高版本上,可以使用imul ax, cx
来真正执行ax *= cx
而不浪费时间写入dx
。)mov ax, 50
。或者使用mov ax, 5 * 10
让汇编器为你完成它。但是,像我说的那样,我相信你已经知道了这个!mul
文档可以在这里以及其他一些站点找到。这些信息可能有点复杂,但只要努力一下,你就应该能够提取所需的信息。你还会在x86标签wiki中找到很多其他的优秀信息和链接。mul
指令之后,你应该会看到ax
和dx
寄存器的内容发生变化。如果你的调试器显示了标志或指令指针,你还将看到它们发生变化。除此之外,没有任何其他的变化!(英特尔指令参考手册中mul
的入口没有列出机器mul
指令有两个操作数:一个是指定的,另一个是隐含的。mul cx
时,它的意思类似于:ax = ax * cx
。dx:ax = ax * cx
- 全部 32 位乘积的高半部分总是被写入 dx
。对于小乘积结果能“适合”在 ax
中的情况下,dx
将为零。如果你只想要结果的低 16 位,你可以认为它破坏了 dx
1。 mov ax, 5 ; ax = 5
mov cx, 10 ; cx = 10
mul cx ; dx:ax = ax * cx
; So ax = ax * cx
; and dx=0 because the product happens to be small.
脚注 1:186支持 imul dst, src, constant
,例如 imul ax, cx, 5
,允许使用任何寄存器而不会隐式使用AX或DX。
386允许使用 imul reg,reg
进行非扩展乘法,没有隐式的寄存器使用。
https://www.felixcloutier.com/x86/imul 讨论了这两种形式。
当然,如果您可以使用386特性,则可以使用lea
代替imul
进行乘以3、5或9的操作,使用允许缩放索引的32位地址模式(即内置移位计数)。
mov ecx, 10
lea ax, [ecx + ecx*4]
imul ax,cx
来执行非扩展乘法(仅使用16位低半部分)。或者186 mov cx,10
/ imul ax,cx,5
来使用立即源执行ax = cx * 5
。(或者386 lea ax,[ecx + ecx * 4]
更便宜地乘以5。) - Peter Cordes
mov bx, 5
==>mov ax, 5
- Weather Vaneimul bx, bx, 10
用一个常数(作为立即值)进行乘法运算。 - Peter Cordes