这是在DosBox 0.74
上为NASM完成的; Input: Requests two integers from the user.
; Output: Outputs the multiplication and division of the input integers.
%include "io.mac"
.STACK 100H
.DATA
prompt_msg1 db "Please input the first number: ",0
prompt_msg2 db "Please input second number: ",0
mul_msg db "multiplication N1 * N2 is: ",0
div_msg db "Division N1/N2 is: ", 0
rem_msg db "Remainder N1/N2 is: ", 0
.CODE
.STARTUP
PutStr prompt_msg1 ; request first number
GetInt CX ; CX = first number
nwln
PutStr prompt_msg2 ; request second number
GetInt DX ; DX = second number
nwln
;multiplication call
call multi ; returns multiplication in BX
PutStr mul_msg ; display multiplication message
PutInt AX ; display multiplication result
;division call
call divis ; returns division in BX
PutStr div_msg ; display Division message
PutInt BX ; display quotient result
nwln
PutStr rem_msg ; display remainder message
PutInt DX ; display remainder result
done:
.EXIT
multi:
mov AX, CX ; imul= first number
imul AX, DX ; imul = imul * second number
ret ; return
divis:
mov BX, CX
div DX ; idiv = first number / second number
ret ; return
更新:
我能够使用社区提供的修复和建议来运行代码,感谢您的所有帮助,这里是更新并运行的代码:
; Input: Requests two integers from the user.
; Output: Outputs the multiplication and division of the input integers.
%include "io.mac"
.STACK 100H
.DATA
prompt_msg1 db "Please input the first number: ",0
prompt_msg2 db "Please input second number: ",0
mul_msg db "multiplication N1 * N2 is: ",0
div_msg db "Division N1/N2 is: ", 0
rem_msg db "Remainder N1/N2 is: ", 0
.CODE
.STARTUP
PutStr prompt_msg1 ; request first number
GetInt CX ; CX = first number
nwln
PutStr prompt_msg2 ; request second number
GetInt DX ; DX = second number
nwln
;multiplication call
call multi ; returns multiplication in BX
PutStr mul_msg ; display multiplication message
PutInt AX ; display multiplication result
;division call
call divis ; returns division in BX
PutStr div_msg ; display Division message
PutInt AX ; display quotient result
nwln
PutStr rem_msg ; display remainder message
PutInt DX ; display remainder result
done:
.EXIT
multi:
mov AX, CX ; imul= first number
imul AX, DX ; imul = imul * second number
ret ; return and clear parameters
divis:
mov BX, DX
mov AX, CX
cwd
idiv BX ; idiv = first number / second number
ret ; return and clear parameters
答案 0 :(得分:2)
div DX
一定会失败。
正如您在英特尔手册中所看到的那样:
DIV
由r / m16签名除以DX:AX
,结果存储在AX
←商,DX
←剩余。
进一步向下:
temp←DX:AX / SRC; (*签名师*)
IF(temp> 7FFFH)或(temp <8000H)
(*如果阳性结果大于7FFFH
或者否定结果小于8000H *)
THEN
#DE; (*除错*)
也就是说,DIV r16
实际上会将DX
和AX
形成的双字划分为r16
,且商必须符合一个单词,否则您将得到一个划分错误。
DX:AX / DX
会为您提供0x1nnnn
的商数,但不适合单词。
因此,您需要为除数使用不同的寄存器,并且还应使用CWD
将被除数符号扩展为DX:AX
。例如:
mov bx,dx
cwd
div bx
答案 1 :(得分:1)
第一个数字位于CX
。第二个数字位于DX
。
divis 除法子程序有3个问题。
CX
)放入累加器BX
时,会将其带到AX
。DX:AX
除以操作数,因此您需要事先初始化DX
。DX
无法同时满足这两个目的(分隔线和扩展分红)的问题。您可以通过以下方式解决这些问题:
mov bx, dx ;Divider (2nd number) to BX
mov ax, cx ;Dividend (1st number) to AX
cwd ;Extend dividend in DX:AX
idiv bx ;Signed division -> Quotient AX, Remainder DX
PutInt BX ; display quotient result
为了显示商,你需要写
PutInt AX
来自评论
根据我的说明,我知道一旦进行了分割,剩余部分将被存储在较小尺寸的寄存器中(假设AX被DX分割,则quoutient将保留在AX中,但剩下的将是存储在例如AL或AH上)是我的理由还是可能我错了?
根据除数的大小,除法有多种方式。对于股息,你没有自由选择。这总是将成为累加器或累加器及其扩展。
字节除法:将字大小的被除数(总是AX
)除以任何字节大小的除数
div bl ; Divides AX by BL
分词:将双倍大小的红利(总是DX:AX
)除以任何单词大小的除数
div cx ; Divides DX:AX by CX
Dword division :将qword大小的红利(始终为EDX:EAX
)除以任何双倍大小的除数
div esi ; Divides EDX:EAX by ESI
商总是在红利的下半部分返回。
字节分割:AX
的下半部分为AL
分词:DX:AX
的下半部分为AX
Dword division :EDX:EAX
的下半部分为EAX
余额总是在红利的上半部分返回。
字节分割:AX
的上半部分为AH
分词:DX:AX
的上半部分为DX
Dword division :EDX:EAX
的上半部分为EDX