您非常需要開始使用空格來分隔您的彙編代碼。這段代碼正在做點什麼極其簡單(將一個數字除以另一個數字),但它是極端難以閱讀。這顯然不應該是這樣的:簡單的代碼應該很容易閱讀!爲什麼很難閱讀?因爲你已經將所有的樣板代碼擠在了實際上正在進行分區操作的代碼上,而且我的眼睛只是咕gla着。我無法從樣板中挑出重要的部分。空白是免費的;不要害怕它。你的彙編器不介意。
寫這樣的:
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會讓你擺脫sl,,但不要陷入不良習慣。這是讓您的代碼無法閱讀並獲得錯誤結果的另一種方法。有跡象表明,你可以在你的代碼中使用符號兩種不同的方式:一種方式是使用地址/偏移符號的,而另一種方法是使用內容/該符號的價值。在MASM/TASM中,當您想要地址/偏移量時,您需要使用OFFSET
關鍵字。當你使用內容/值時,你在技術上並不需要,但是如果應該將括號中的符號包裝起來以表示它被解除引用。換句話說,而不是,:
mov ax, num1
寫它:
mov ax, [num1]
隨着那誇誇其談了我的胸口,讓我們來看看什麼是你的代碼錯誤。邁克爾佩奇已經指出,這是MASM/TASM的「做我的意思,而不是我寫的」風格的另一種情況是沒有任何好處。它正在做一個8位除法,因爲你已經用DIV
指令使用了一個8位操作數(num2
)。這意味着它實際上做:
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」表示寄存器或內存操作數。
您使用[DIV](http://www.felixcloutier.com/x86/DIV.html)指令的形式是'由R/M8無符號除法,AX,與存儲在AL←商數,AH結果←剩下的。這是因爲MASM/TASM默認'num1'是一個8位內存操作數,因爲定義爲'num2 db 02h'。在這種情況下,不使用_DX_(因此它的值無關緊要)。什麼是錯誤的是0x204除以2是0x102。 0x102不能放在一個字節中(字節爲0x00到0xff),因爲商不能放入8個字節的寄存器(_AL_),所以會導致除法異常(溢出)。 –
爲了得到這個工作,你就必須比0淘汰16位寄存器,MOV'num2'到該寄存器的低8位,設置_DX_爲零,並做了16位除法運算(而不是8)。從我的第一條評論的鏈接中,指令的形式是'無符號除法DX:AX by r/m16,結果存儲在AX←商數,DX←餘數。當師完成0x102應該在_AX_ –