装配中的MUL功能

Jam*_*ark 6 x86 assembly multiplying

我试图在汇编中进行简单的乘法操作,但由于某种原因,我没有看到寄存器在标记MUL功能时发生变化.

mov bx, 5    
mov cx, 10

mul cx
Run Code Online (Sandbox Code Playgroud)

Cod*_*ray 29

这些被称为指令,和他们指定的操作要由处理器来执行.mov对于mov e来说mul是一个助记符,而对于mul tiply来说则是一个助记符.其他常见的指令包括add,sub和div.我相信你可以弄清楚这些指定的操作!

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

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

因此,您可以想象这mul cx意味着mul ax, cx,但您不会这样写,因为ax目标寄存器是隐式的.

现在,mul指令命令处理器将目标操作数乘以源操作数,并将结果存储在目标中.在代码中,您可以想象mul cx会转化为ax = ax * cx.现在你应该看到问题所在:你还没有初始化ax寄存器的内容,所以你将cx剩下的垃圾乘以10(这是你放入的值)ax.因此,结果毫无意义!

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

mov  ax, 5     ; ax = 5
mov  cx, 10    ; cx = 10
mul  cx        ; ax = ax * cx
Run Code Online (Sandbox Code Playgroud)

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

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

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

但由于某种原因,我没有看到标记MUL功能时寄存器发生变化.

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

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

  • 好答案。还值得注意的是;即使产品小到足以容纳该产品的两个寄存器中的第一个,所得到的产品也将使高阶寄存器归零。 (2认同)

Mos*_*ael 6

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

当你写的时候,mul cx它的意思是这样的:ax = ax * cx。

实际上,这意味着dx:ax = ax * cx- 完整 32 位产品的高半部分始终写入dx. dx对于结果“适合”的小型产品,该值为零ax。如果您只想要结果的低 16 位,您可以将其视为破坏dx1。

你的问题的答案,如果你真的想将 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.
Run Code Online (Sandbox Code Playgroud)

脚注 1:186 允许imul dst, src, constantlike imul ax, cx, 5,允许任何寄存器而不隐式使用 AX 或 DX。
386 允许imul reg,reg在没有隐式寄存器的情况下进行非加宽乘法。
https://www.felixcloutier.com/x86/imul涵盖了这两种形式。

当然,如果您可以使用 386 个功能,您可以使用允许缩放索引(即内置移位计数)的 32 位寻址模式lea来imul代替乘以 3、5 或 9。

  mov  ecx, 10
  lea  ax, [ecx + ecx*4]
Run Code Online (Sandbox Code Playgroud)

  • 第一次就准确地描述它,而不是添加更正,会更容易、更好。我做了一个编辑,我认为它同样易于阅读,但并不意味着有任何需要纠正的地方。 (2认同)