输入带符号的一位十进制数的输出

问题描述 投票:0回答:1

我的这段代码有问题。

 .model small
.stack 100h

.data
    Msg1 DB 'Enter first number: $'
    Msg2 DB 10, 13, 'Enter second number: $'
    Msg3 DB 10, 13, 'Entered numbers are: $'
    PositiveMsg DB ' is positive$'
    NegativeMsg DB ' is negative$'
    InputBuffer DB 6 DUP('$')

.code
main proc
    mov ax, @data
    mov ds, ax

    ; Display message asking for the first number
    mov ah, 09h
    lea dx, Msg1
    int 21h

    ; Read the first number from the user
    mov ah, 01h
    int 21h
    sub al, '0'          ; Convert ASCII character to its corresponding numeric value
    mov bh, al           ; Move the numeric value of the first number to BH

    ; Determine if the first number is positive or negative
    cmp al, 0
    jge FirstPositive
    mov dx, OFFSET NegativeMsg  ; Display negativity message for the first number
    int 21h
    neg bh               ; Negate the value to make it positive
    jmp CheckSecondNumber
FirstPositive:
    mov dx, OFFSET PositiveMsg  ; Display positivity message for the first number
    int 21h

CheckSecondNumber:
    ; Display message asking for the second number
    mov ah, 09h
    lea dx, Msg2
    int 21h

    ; Read the second number from the user
    mov ah, 01h
    int 21h
    sub al, '0'          ; Convert ASCII character to its corresponding numeric value
    mov dh, al           ; Move the numeric value of the second number to DH

    ; Determine if the second number is positive or negative
    cmp al, 0
    jge SecondPositive
    mov dx, OFFSET NegativeMsg  ; Display negativity message for the second number
    int 21h
    neg dh               ; Negate the value to make it positive
    jmp DisplayNumbers
SecondPositive:
    mov dx, OFFSET PositiveMsg  ; Display positivity message for the second number
    int 21h

DisplayNumbers:
    ; Display message indicating the entered numbers
    mov ah, 09h
    lea dx, Msg3
    int 21h

    ; Display the first entered number
    mov dl, bh           ; Move the numeric value of the first number to DL
    add dl, '0'          ; Convert numeric value to its corresponding ASCII character
    mov ah, 02h
    int 21h

    ; Display the positivity/negativity message for the first number
    mov dx, OFFSET PositiveMsg
    int 21h

    ; Display a comma between the numbers
    mov dl, ','         
    int 21h

    ; Display the second entered number
    mov dl, dh           ; Move the numeric value of the second number to DL
    add dl, '0'          ; Convert numeric value to its corresponding ASCII character
    mov ah, 02h
    int 21h

    ; Display the positivity/negativity message for the second number
    mov dx, OFFSET PositiveMsg
    int 21h

    ; Exit program
    mov ah, 4Ch
    int 21h
main endp

end main

这是错误输出的Msg3。它应该显示输入的数字并确定它是正数还是负数:
screenshot

我已经尝试了不同的代码,但 Msg3 的输出仍然是错误的。

assembly x86-16 dosbox
1个回答
0
投票

输出混乱的主要原因是在调用 DOS 打印消息之前没有指定所需的函数编号 AH=09h,以及使用 DH 保存第二个编号,同时使用 DX 进行其他用途。请记住,16 位 DX 由两个 8 位部分 DH 和 DL 组成。

输入带符号的一位十进制数

DOS.GetCharacter函数01h首先等待用户按下键盘按键,然后将相应的字符写入屏幕上,最后将AL寄存器中的按键的ASCII码返回给您的程序。对于某些特殊键,该函数将返回 AL=0,这样 表明您的程序应再次调用该函数以获取按键的扫描码。

如果您希望用户能够输入带符号的一位十进制数,那么在[-9,9]范围内,您将不得不采取两步方法。如果您第一次使用该函数时已经收到一个数字 [0,9],那么您可以跳过第二步。另一方面,如果您收到的第一个字符碰巧是减号字符,那么您必须再次调用该函数,期望得到一个数字 [0,9],而这次您还必须对数字求反。
下一个简化示例验证用户输入:

ReDo1:
  mov  ah, 01h       ; DOS.GetCharacter
  int  21h           ; -> AL
  sub  al, '0'
  cmp  al, 10
  jb   GotIt         ; Is positive [0,9]
  cmp  al, '-' - '0'
  jne  ReDo1         ; An invalid character detected
ReDo2:
  mov  ah, 01h       ; DOS.GetCharacter
  int  21h           ; -> AL
  sub  al, '0'
  cmp  al, 10
  jae  ReDo2         ; Not a decimal digit
  neg  al
GotIt:

你不想重复太多,所以你应该把上面的内容放在一个子程序中。

  mov  dx, OFFSET Msg1 ; Read the first number from the user
  call Input           ; -> AL
  mov  bl, al    
  mov  dx, OFFSET Msg2 ; Read the second number from the user
  call Input           ; -> AL
  mov  bh, al    

  ...

; IN (dx) OUT (al) MOD (ah)
Input:
  mov  ah, 09h       ; DOS.PrintString
  int  21h
ReDo1:
  mov  ah, 01h       ; DOS.GetCharacter
  int  21h           ; -> AL
  sub  al, '0'
  cmp  al, 10
  jb   GotIt         ; Is positive [0,9]
  cmp  al, '-' - '0'
  jne  ReDo1         ; An invalid character detected
ReDo2:
  mov  ah, 01h       ; DOS.GetCharacter
  int  21h           ; -> AL
  sub  al, '0'
  cmp  al, 10
  jae  ReDo2         ; Not a decimal digit
  neg  al
GotIt:
  ret

输出带符号的一位十进制数

仅添加“0”并让 DOS 显示一个字符是不够的。按顺序进行负数测试,如果需要,则输出减号字符:

  test bl, bl
  jns  IsPositive
  mov  dl, '-'
  mov  ah, 02h        ; DOS.PrintChar
  int  21h
IsPositive:
  lea  dx, [bx - '0'] ; BH and DH are un-important here
  mov  ah, 02h        ; DOS.PrintChar
  int  21h

显示最终总结消息也可以从使用子例程中受益。我确实包含了区分您的 PositiveMsgNegativeMsg 消息的必要逻辑,这是您忘记做的事情:

  mov  dx, OFFSET Msg3   ; BL contains first number
  call Output
  mov  bl, bh            ; Load second number in BL
  mov  dx, OFFSET Msg4   ; Make this a ', $'
  call Output

  ...

; IN (bl,dx) OUT () MOD (ax,dx)
Output:
  mov  ah, 09h       ; DOS.PrintString
  int  21h
  test bl, bl
  jns  IsPositive1
  mov  dl, '-'
  mov  ah, 02h       ; DOS.PrintChar
  int  21h
IsPositive1:
  lea  dx, [bx - '0'] ; BH and DH are not important here
  mov  ah, 02h        ; DOS.PrintChar
  int  21h
  mov  dx, OFFSET PositiveMsg
  test bl, bl
  jns  IsPositive2
  mov  dx, OFFSET NegativeMsg
IsPositive2:
  mov  ah, 09h
  int  21h
  ret
© www.soinside.com 2019 - 2024. All rights reserved.