DIV指令跳转到随机位置?

时间:2017-04-20 14:22:29

标签: assembly x86 x86-16 dos tasm

所以我有this exact problem

给出的解决方案是将DX归零,但就我而言,它已经是! 我的程序是简单地将16位数字除以8位数。

我的代码是:

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

任何解决方案?

1 个答案:

答案 0 :(得分:3)

您非常需要开始使用空格来分隔汇编代码。这段代码正在做简单(将一个数字除以另一个数字),但难以阅读。显然不应该这样:简单的代码应该易于阅读!为什么难以阅读?因为你的所有样板代码都被实际执行分割操作的代码卡住了,我的眼睛只是茫然。我无法从样板中找出重要的部分。空白是免费的;不要害怕它。你的装配工并不介意。

像这样写:

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会让你摆脱邋,,但不要养成坏习惯。这是使您的代码不可读并获得错误结果的另一种方法。在代码中使用符号有两种不同的方法:一种方法是使用该符号的地址 / 偏移,另一种方法是使用<该符号的em> contents / value 。在MASM / TASM中,如果需要地址/偏移量,则需要使用OFFSET关键字。当你使用内容/值时,你在技术上并不需要,但你真的将符号包装在括号中以表明它被解除引用。换句话说,而不是:

mov ax, num1

写下来:

mov  ax, [num1]

随着我的胸膛咆哮,让我们来看看你的代码有什么问题。 Michael Petch已经指出,这是另一个案例,其中MASM / TASM的“做我的意思,而不是我写的”风格并没有给你任何好处。它正在进行8位除法,因为您使用了带有num2指令的8位操作数(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来保存其原始值。)

documentation for the DIV instruction包含一个方便的表格,总结了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”表示寄存器或内存操作数。