您迫切需要开始使用空格来分隔汇编代码。这段代码正在做一些事情极其简单(一个数字除以另一个数字),但它是极其很难阅读。显然情况并非如此:简单的代码应该易于阅读!为什么读书难?因为你所有的样板代码都与实际执行除法运算的代码相冲突,而我的眼睛却呆滞了。我无法从样板中找出重要的部分。空白是免费的;不要害怕它。你的汇编器不介意。
像这样写:
data segment
num1 dw 0204h
num2 db 02h
quotient db ?
remainder db ?
data ends
code segment
assume cs:code, ds:data
start:
; Initialize Data Segment (DS)
mov ax, data
mov ds, ax
; Do the division and save the results
mov ax, num1
div num2
mov quotient, al
mov remainder, ah
; Terminate process
; (Note that you should also be setting AL to a result code here!)
mov ah, 4ch
int 21h
end start
code ends
现在,是不是更清楚什么是什么了?另外,虽然 MASM/TASM 可以让你避免马虎,但不要养成坏习惯。这是另一种使代码不可读并得到错误结果的方法。在代码中使用符号有两种不同的方法:一种方法是使用address/offset该符号的另一种方法是使用contents/value那个符号的。在MASM/TASM中,当需要地址/偏移量时,需要使用OFFSET
关键词。当您使用内容/值时,从技术上讲您不需要这样做,但您确实should将符号括在方括号中以指示它正在被取消引用。换句话说,而不是:
mov ax, num1
写下来:
mov ax, [num1]
说了这么多,让我们看看你的代码出了什么问题。 Michael Petch 已经指出,这是 MASM/TASM 的“做我的意思,而不是我写的”风格的另一个例子,这对你没有任何好处。它正在执行 8 位除法,因为您使用了 8 位操作数 (num2
)与DIV
操作说明。这意味着它实际上正在做:
AX / [num2]
商在AL
其余的在AH
。如果商大于8位,则无法容纳AL
并且分裂将会溢出。
解决方法是进行 16 位除法,在这种情况下,商将被放入AX
其余的将被放置在DX
.
为此,请这样编写代码:
mov ax, [num1] ; AX = [num1]
xor dx, dx ; DX = 0
xor bx, bx ; BX = 0
mov bl, [num2] ; BL = [num2], BH = 0
div bx ; DX:AX / BX
mov [quotient], ax
mov [remainder], dx
(因为这也很糟糕BX
,您可能想通过执行以下操作来保存其原始值push bx
在顶部和一个pop bx
在最后。)
The 的文档DIV操作说明 http://x86.renejeschke.de/html/file_module_x86_id_72.html包含一个方便的表格,总结了 8 位、16 位和 32 位除法的工作原理:
Operand Size | Dividend | Divisor | Quotient | Remainder | Maximum Quotient
--------------------------------------------------------------------------------------
Word/byte | AX | r/m8 | AL | AH | 2^8 - 1
Doubleword/word | DX:AX | r/m16 | AX | DX | 2^16 - 1
Quadword/doubleword | EDX:EAX | r/m32 | EAX | EDX | 2^32 - 1
“除数”是唯一的操作数DIV
操作说明。 “红利”是隐含的。请注意,“r/m”表示寄存器或内存操作数。