问题描述
所以我有.
给出的解决方案是将DX
归零,但就我而言,已经是!我的程序是将16位数字除以8位数字.
The solution given is to zero out DX
, but in my case it already is!
My program is to simply divide a 16 bit number by an 8 bit number.
我的代码是:
data segment
num1 dw 0204h
num2 db 02h
quotient db ?
remainder db ?
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov ax,num1
div num2
mov quotient,al
mov remainder,ah
mov ah,4ch
int 21h
code ends
end start
有解决方案吗?
推荐答案
您非常需要开始使用空格来分隔汇编代码.这段代码做的事情极其简单(将一个数字除以另一个),但极端的却很难阅读.显然不是这样:简单的代码应该易于阅读!为什么很难阅读?因为您的所有样板代码都与实际执行除法操作的代码相对应,所以我的眼睛不知所措.我无法从样板中挑选出重要的部分.空格是免费的;不要害怕.您的汇编程序不介意.
You badly need to start using whitespace to separate your assembly code. This code is doing something extremely simple (dividing one number by another), yet it is extremely difficult to read. That should obviously not be the case: simple code should be simple to read! Why is it hard to read? Because you've got all of your boilerplate code jammed up against the code that's actually doing the division operation, and my eyes just glaze over. I'm not able to pick out the important bits from the boilerplate. Whitespace is free; don't be afraid of it. Your assembler doesn't mind.
这样写:
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会让您摆脱草率的习惯,但不要养成不良习惯.这是使代码无法读取并获得错误结果的另一种方法.您可以在代码中使用符号的两种不同方法:一种方法是使用该符号的地址/偏移量,另一种方法是使用 contents / value .在MASM/TASM中,当您需要地址/偏移量时,需要使用OFFSET
关键字.使用内容/值时,从技术上讲您并不需要,但实际上应该将符号括在方括号中以表明它已被取消引用.换句话说,而不是:
Now, isn't it substantially more clear what's what? Also, while MASM/TASM will let you get away with being sloppy, don't get into bad habits. That's another way to make your code unreadable and get the wrong results. There are two different ways that you can use symbols in your code: one way is to use the address/offset of that symbol, and the other way is to use the contents/value of that symbol. In MASM/TASM, when you want the address/offset, you need to use the OFFSET
keyword. When you use the contents/value, you don't technically need to, but you really should wrap the symbol in brackets to indicate that it is being dereferenced. In other words, instead of:
mov ax, num1
写出来:
mov ax, [num1]
带着这怒吼,让我们看看您的代码有什么问题.迈克尔·佩奇(Michael Petch)已经指出,这是MASM/TASM的按我的意思而不是我所写的"风格对您没有任何帮助的另一种情况.之所以执行8位除法,是因为您在DIV
指令中使用了8位操作数(num2
).这意味着它实际上在做:
With that rant off my chest, let's look at what's wrong with your code. Michael Petch has already pointed out that this is another case where MASM/TASM's "do what I mean, not what I write" style is not doing you any favors. It is doing an 8-bit division because you've used an 8-bit operand (num2
) with the DIV
instruction. That means it's actually doing:
AX / [num2]
,商为AL
,余数为AH
.如果商大于8位,则它不适合AL
,并且除法将溢出.
with the quotient in AL
and the remainder in AH
. If the quotient is larger than 8 bits, it won't fit in AL
and the division will overflow.
解决方法是进行16位除法,在这种情况下,商将被放置在AX
中,其余部分将被放置在DX
中.
The workaround is to do a 16-bit division, in which case the quotient will be placed in AX
and the remainder will be placed in DX
.
要实现这一点,请编写以下代码:
To get that, write the code thusly:
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
来保存其原始值.)
(Since this is also clobbering BX
, you may want to save its original value by doing a push bx
at the top and a pop bx
at the end.)
DIV
指令的文档包含一个方便的表格,该表格总结了8位,16位和32位除法:
The documentation for the DIV
instruction contains a handy table summarizing how 8-bit, 16-bit, and 32-bit divisions work:
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"表示寄存器或内存操作数.
The "divisor" is the sole operand for the DIV
instruction. The "dividend" is implicit. Note that "r/m" means either a register or memory operand.
这篇关于DIV指令跳转到随机位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!