装配中的MUL功能

时间:2016-11-30 16:12:05

标签: assembly x86 multiplying

我正在尝试在汇编中进行简单的乘法操作,但出于某种原因,当标记MUL函数时,我看不到寄存器的变化。

mov bx, 5    
mov cx, 10

mul cx

2 个答案:

答案 0 :(得分:20)

这些称为指令,它们指定由处理器执行的操作mov mov e的助记符,而mul mul 的助记符。其他常见说明包括addsubdiv。我相信你可以弄清楚这些指定的操作!

大多数说明都有两个参数。在技​​术术语中,这些术语通常称为操作数。第一个(左侧)是目的地,第二个(右侧)是。因此,在mov bx, 5的情况下,这会将字面值5移动到目标寄存器bx中。当然,这些参数的顺序很重要,因为您无法将寄存器bx的内容移动到文字值5中!

mul指令有点奇怪,因为它的一些操作数是隐含的。也就是说,它们没有明确指定为参数。对于mul指令,目标操作数被硬编码为ax寄存器。源操作数是您作为参数传递的操作数:它可以是寄存器或内存位置。

因此,您可以想象mul cx表示mul ax, cx,但您不会这样写,因为ax目标寄存器是隐含的。

现在,mul指令命令处理器将目标操作数乘以源操作数,并将结果存储在目标中。在代码中,您可以想象mul cx会转换为ax = ax * cx。现在你应该看到问题了:你还没有初始化ax寄存器的内容,所以你将cx中的值乘以ax中的值,乘以mov ax, 5 ; ax = 5 mov cx, 10 ; cx = 10 mul cx ; ax = ax * cx 中的任何垃圾。 1}}。因此,结果毫无意义!

如果您确实想要做5 * 10,那么您只需更改代码中的一个字符:

ax

结果将存储在dx:ax中,这是隐式目标寄存器。从技术上讲,结果将存储在dx中。这是一个寄存器对,意味着结果的高部分将存储在ax中,而结果的低部分将存储在mul中。为什么这个额外的并发症?因为乘以两个16位值可能会导致值大于16位!将结果返回到16位寄存器的中,允许ax指令返回32位结果。但是,当你刚刚学习时,你不必担心这一点。您可以忽略溢出的可能性,并从mov ax, 50中提取结果的低部分。

虽然我确信这只是一个玩具示例,但实际上没有理由编写将两个常数相乘的代码。这可以在构建时完成,使用计算器并对值进行硬编码,或者象征性地写出常量的乘法并让汇编程序进行计算。也就是mul。但就像我说的那样,我相信你已经知道了!

如果所有其他方法都失败了,请查阅文档,了解给您带来麻烦的说明。你几乎总能通过谷歌搜索指令的名称和“x86”在线找到它。例如,可以找到mul文档here以及其他几个站点。这些信息可能有点复杂,但通过一些努力,您应该能够提取所需的信息。您还可以在代码wiki中找到许多其他重要信息和链接。

  

但由于某种原因,当标记MUL功能时,我看不到寄存器的变化。

我还应该指出,如果您使用调试器来逐步执行代码,则当前标记/突出显示的行是 about 要执行的行。它尚未执行,因此它对寄存器,内存等的影响尚不可见。您必须跳过指令,以便标记/高亮显示在 next 行上,然后您将看到前一个(刚刚执行的)指令的效果。

如果你理解了我上面的解释,在ax指令之后,你应该看到dx和{{1}}寄存器的内容发生了变化。如果调试器显示其中任何一个,您还将看到标志和指令指针的变化。别的什么都不应该改变! (英特尔的说明参考手册未列出对机器架构状态的任何其他影响。)

答案 1 :(得分:3)

mul指令有2个操作数:一个被指定,另一个是隐式的。

当您写mul cx时,其含义类似于:ax = ax * cx

实际上,这意味着dx:ax = ax * cx-完整的32位乘积的高半部分始终写入dx。对于结果“符合” dx的小型产品,ax将为零。如果只希望结果的低16位,则可以将其视为破坏dx 1

问题的答案,如果您真的想将5乘以10,则可以执行以下操作:

  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, constantimul 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]