如何在汇编语言emu8086中正确使用div?
How to use div properly in Assembly language emu8086?
我正在开发一个汇编语言程序,该程序将检查输入的数字是否 div3 是否可用,现在我正在努力使事情正确,但我的代码是 运行..似乎 dx 寄存器的内容始终为零,即使在执行 div 之后也是如此..
org 100h
jmp main
msg_prpt: db 'Enter a number (1-9): $'
msg_err: db 0dh, 0ah, 'Number out of range. $'
msg_1: db 0dh, 0ah, 'Number is divisible by 3. $'
msg_2: db 0dh, 0ah, 'Number is not divisible by 3. $'
num: db ?
num1 dw ?
display:
mov ah, 9h ; "display string" function for int 21h
int 21h
ret
dsp_prpt:
mov dx, msg_prpt ; copy contents of msg_prompt to dx
call display
ret
dsp_err:
mov dx, msg_err ; copy contents of msg_err to dx
call display
ret
get_num:
mov ah, 1h ; "character input" function for int 21h (stored in al)
int 21h
mov [num], al ; copy contents of al to space at address [num]
mov num1,num
ret
;checking if the inputted number is divisible by 3
validateDivisibleby3:
mov dx,0
mov ax,num ; copy character to ax for comparison
mov bx,03h
idiv bx
cmp dx,0
je isMultipleof3:
call isNotMultipleof3
ret
convert:
sub al, 30h ; subtract 30h from input to get numeric from ascii
ret
isMultipleof3:
; print the result:
mov dx, msg_2 ; copy contents of msg_prompt to dx
call display
ret
isNotMultipleof3:
; print the result:
mov dx, msg_1 ; copy contents of msg_prompt to dx
call display
ret
exit:
; wait for any key press:
mov ah, 0
int 16h
ret ; return control to operating system.
main:
call dsp_prpt
call get_num
call validateDivisibleby3
call convert
call exit
非常感谢您的帮助....
mov dx, msg_prpt
你确定你用的是emu8086吗?由于 emu8086 使用 MASM 样式,加载消息的地址必须是 mov dx, OFFSET msg_prpt
或(但这是一个字节长)lea dx, msg_prpt
。您的程序加载了很多地址,所以这很重要。
I am struggling to get things correct
您的代码未显示正确结果的原因:
- 您将输入从字符转换为 [1,9] 范围内的值太晚了。测试使用的是 ASCII 代码。
- 您检查的值是使用
mov ax, num
从 num 变量中获取的,但是 num 变量只是一个字节大小的变量。汇编程序应该对此有所抱怨,然后 emu8086 又充满了怪癖......
mov num1,num
应该做什么? emu8086 接受这个吗?无论它做什么都会影响您从地址 num. 加载的 word
- 您错误地引用了那些 ...Multipleof3 代码中的相反消息。
- 注意
je isMultipleof3:
中的语法。即使 emu8086 接受了这个尾随冒号,我也不相信它会生成正确的代码。
鉴于您使用的是 1 到 9 范围内的值,因此使用 word-sized 除法有点矫枉过正。接下来的代码使用 byte-sized 除法。我还简化了分支。
get_num:
mov ah, 01h ; "character input" function for int 21h
int 21h ; -> AL
sub al, 30h ; subtract 30h from input to get numeric from ascii
mov [num], al ; copy contents of al to space at address [num]
ret
validateDivisibleby3:
mov al, [num]
mov ah, 0 ; (*)
mov bl, 3
div bl ; AX / BL --> AL quotient, AH remainder
mov dx, OFFSET msg_1 ; Divisible
test ah, ah ; Is remainder 0 ?
jz display ; Yes
mov dx, OFFSET msg_2 ; Not Divisible
; IN (dx)
display:
mov ah, 09h
int 21h
ret
(*) 使用 cbw
会减少一个字节。您可以安全地使用它,因为您知道该值是 AL
是一个正数。
危险
exit:
mov ah, 0
int 16h
ret ; return control to operating system.
你不能call
退出 然后期望 return 到 DOS 只用 ret
指令! call
指令将在堆栈上放置一些 return 地址,但它不是 return DOS 控制的正确 return 地址。
存在几种选择。快速修复是用 jmp exit
.
替换 call exit
我正在开发一个汇编语言程序,该程序将检查输入的数字是否 div3 是否可用,现在我正在努力使事情正确,但我的代码是 运行..似乎 dx 寄存器的内容始终为零,即使在执行 div 之后也是如此..
org 100h
jmp main
msg_prpt: db 'Enter a number (1-9): $'
msg_err: db 0dh, 0ah, 'Number out of range. $'
msg_1: db 0dh, 0ah, 'Number is divisible by 3. $'
msg_2: db 0dh, 0ah, 'Number is not divisible by 3. $'
num: db ?
num1 dw ?
display:
mov ah, 9h ; "display string" function for int 21h
int 21h
ret
dsp_prpt:
mov dx, msg_prpt ; copy contents of msg_prompt to dx
call display
ret
dsp_err:
mov dx, msg_err ; copy contents of msg_err to dx
call display
ret
get_num:
mov ah, 1h ; "character input" function for int 21h (stored in al)
int 21h
mov [num], al ; copy contents of al to space at address [num]
mov num1,num
ret
;checking if the inputted number is divisible by 3
validateDivisibleby3:
mov dx,0
mov ax,num ; copy character to ax for comparison
mov bx,03h
idiv bx
cmp dx,0
je isMultipleof3:
call isNotMultipleof3
ret
convert:
sub al, 30h ; subtract 30h from input to get numeric from ascii
ret
isMultipleof3:
; print the result:
mov dx, msg_2 ; copy contents of msg_prompt to dx
call display
ret
isNotMultipleof3:
; print the result:
mov dx, msg_1 ; copy contents of msg_prompt to dx
call display
ret
exit:
; wait for any key press:
mov ah, 0
int 16h
ret ; return control to operating system.
main:
call dsp_prpt
call get_num
call validateDivisibleby3
call convert
call exit
非常感谢您的帮助....
mov dx, msg_prpt
你确定你用的是emu8086吗?由于 emu8086 使用 MASM 样式,加载消息的地址必须是 mov dx, OFFSET msg_prpt
或(但这是一个字节长)lea dx, msg_prpt
。您的程序加载了很多地址,所以这很重要。
I am struggling to get things correct
您的代码未显示正确结果的原因:
- 您将输入从字符转换为 [1,9] 范围内的值太晚了。测试使用的是 ASCII 代码。
- 您检查的值是使用
mov ax, num
从 num 变量中获取的,但是 num 变量只是一个字节大小的变量。汇编程序应该对此有所抱怨,然后 emu8086 又充满了怪癖......
mov num1,num
应该做什么? emu8086 接受这个吗?无论它做什么都会影响您从地址 num. 加载的 word
- 您错误地引用了那些 ...Multipleof3 代码中的相反消息。
- 注意
je isMultipleof3:
中的语法。即使 emu8086 接受了这个尾随冒号,我也不相信它会生成正确的代码。
鉴于您使用的是 1 到 9 范围内的值,因此使用 word-sized 除法有点矫枉过正。接下来的代码使用 byte-sized 除法。我还简化了分支。
get_num:
mov ah, 01h ; "character input" function for int 21h
int 21h ; -> AL
sub al, 30h ; subtract 30h from input to get numeric from ascii
mov [num], al ; copy contents of al to space at address [num]
ret
validateDivisibleby3:
mov al, [num]
mov ah, 0 ; (*)
mov bl, 3
div bl ; AX / BL --> AL quotient, AH remainder
mov dx, OFFSET msg_1 ; Divisible
test ah, ah ; Is remainder 0 ?
jz display ; Yes
mov dx, OFFSET msg_2 ; Not Divisible
; IN (dx)
display:
mov ah, 09h
int 21h
ret
(*) 使用 cbw
会减少一个字节。您可以安全地使用它,因为您知道该值是 AL
是一个正数。
危险
exit: mov ah, 0 int 16h ret ; return control to operating system.
你不能call
退出 然后期望 return 到 DOS 只用 ret
指令! call
指令将在堆栈上放置一些 return 地址,但它不是 return DOS 控制的正确 return 地址。
存在几种选择。快速修复是用 jmp exit
.
call exit