【问题标题】:Implementing Arithmetic in Assembly在汇编中实现算术
【发布时间】:2020-03-13 08:12:41
【问题描述】:

我是 Winx64 上的 Assembly 的新程序员。我正在尝试设置代码,使用汇编编程中的基本算术将一个数组的值除以另一个数组的值。我无法完成的实验室是这样的:

这是我尝试实现的代码(放置在 Hyper-V 虚拟机中,对于我最终遇到的任何糟糕的缩进感到抱歉):

TITLE DISPLAY
      .MODEL SMALL
      .386
      .STACK
      .DATA
S     EQU 12 ;size of arrays
X     BYTE 4, 16, 100, -116, -68, -104, 125, 60, 99, 33, 55, 77
Y     BYTE 2, 3, 4, -5, -6, -7, -8, -9, -10, 11, 12, 13
Q     BYTE 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0     ;quotient = X/Y
R     BYTE 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0     ;remainder = X/Y

;Address of X is _______:_______
;Address of Y is _______:_______
;Address of Q is _______:_______
;Address of R is _______:_______

      .CODE
MAIN  PROC FAR
      .STARTUP
      ;Program
      MOV ESI, 0       ;use ESI and index to arrays
      MOV CX, S       ;counter for loop

L1:   MOV AX, 0 ;clear the AX register
      MOV AL, [X+ESI] ;load dividend
      MOV BL, [Y+ESI]
      MOV DX, 0 ;clear the DX register
      IDIV AX ;divide X by Y
      MOV [Q+ESI], EAX    ;store quotient in Q
      INC ESI  ;increment index by 1
      LOOP L1
      .EXIT 
MAIN  ENDP
      END

我遇到的第一个问题是第 29 行有错误 A2070:无效的指令操作数。第二个问题是我不确定整个代码是否正确以及错误。我相信我能够在调试器的内存中找到 X 和 Y(特别是 Q 和 R)的值,但是我在首先组装这段代码时遇到了麻烦。

这也是一个 Excel,除了 Q 和 R 的预期值。

【问题讨论】:

  • 确定 main应该是proc far吗?即使对于 16 位代码(.model small.386 之前)(例如Using 32 bit registers in MASM without changing the default segment definition size),这对于 masm / tasm 也是不正常的。既然您显然在编写 16 位代码,为什么要使用 ESI 而不是 SI?即使是您开始的图像也显然是这样做的,这对我来说毫无意义。 SI 是 16 位寻址模式的有效寄存器,但他们使用的是 CX 而不是 ECX,所以很明显他们打算使用 16 位模式。 (32 或 64 会更容易在 64 位 Windows 上运行)
  • 无论如何,这不是问题 - 一个明显的亮点是idiv ax 将 DX:AX 除以 AX。 IDK 为什么您认为 BL 可能是 IDIV 的隐式输入,但事实并非如此。此外,您需要用cwd 签名 扩展,而不是在idiv 之前将被除数零扩展。 8086 assembly on DOSBox: Bug with idiv instruction?。由于这是 .386 代码,因此您可以在将 AX 符号扩展为 DX:AX 之前,使用 movsx 将内存中的字节加载到 AX 等 16 位寄存器中。
  • 哦,您的错误可能出在 32 位 mov 存储到字节数组中。 AL 是您正在计算的 16 位商的 8 位低半部分。顺便说一句,使用 8 位除法会更有意义,除非您担心在 -128 / -1 的极端情况下出现 #DE 错误
  • @JordanMeans 回想一下 Q 是一个字节数组,但 EAX 是一个双字。这里存在类型不匹配。如果商适合 8 位,请使用 MOV [Q+ESI], AL。否则,请适当更改数组元素的数据类型。
  • @fuz 谢谢大家!由于fuz的建议,代码按预期工作!谢谢大家的帮助!

标签: assembly x86 masm integer-division


【解决方案1】:

好的。 fuz 发现的问题是我存储的商不正确。

TITLE DISPLAY
      .MODEL SMALL
      .386
      .STACK
      .DATA
S     EQU 12 ;size of arrays
X     BYTE 4, 16, 100, -116, -68, -104, 125, 60, 99, 33, 55, 77
Y     BYTE 2, 3, 4, -5, -6, -7, -8, -9, -10, 11, 12, 13
Q     BYTE 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0     ;quotient = X/Y
R     BYTE 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0     ;remainder = X/Y

;Address of X is _______:_______
;Address of Y is _______:_______
;Address of Q is _______:_______
;Address of R is _______:_______

      .CODE
MAIN  PROC FAR
      .STARTUP
      ;Program
      MOV ESI, 0       ;use ESI and index to arrays
      MOV CX, S       ;counter for loop

L1:   MOV AX, 0 ;clear the AX register
      MOV AL, [X+ESI] ;load dividend
      MOV BL, [Y+ESI]
      MOV DX, 0 ;clear the DX register
      IDIV AX ;divide X by Y
      MOV [Q+ESI], AL   ;store quotient in Q
      INC ESI  ;increment index by 1
      LOOP L1
      .EXIT 
MAIN  ENDP
      END

【讨论】:

  • 感谢您发布此答案!这是非常有价值的。
猜你喜欢
  • 2016-01-02
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
相关资源
最近更新 更多