如何在汇编语言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. 您将输入从字符转换为 [1,9] 范围内的值太晚了。测试使用的是 ASCII 代码。
  2. 您检查的值是使用 mov ax, numnum 变量中获取的,但是 num 变量只是一个字节大小的变量。汇编程序应该对此有所抱怨,然后 emu8086 又充满了怪癖......
    mov num1,num 应该做什么? emu8086 接受这个吗?无论它做什么都会影响您从地址 num.
  3. 加载的 word
  4. 您错误地引用了那些 ...Multipleof3 代码中的相反消息。
  5. 注意 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