0

我正在尝试编写一个汇编语言程序,它读取一个数字并将其与 5 进行比较。如果数字小于 5,则程序应该成功结束,否则它应该显示错误消息并提示再次输入数字。无论我做什么,我似乎都无法成功结束,它总是跳转到错误标签。

我的代码:

bits 16
org 0x100   ;start at offset 100
jmp main

buffer:   db 4  ; define 4 bytes
      db 0  ; actual number of characters entered

msg:      db "Enter a number between 0 and 5 ", 0ah, 0dh, '$' ; define bytes for message

ermsg:    db "The number must be between 0 and 5", 0ah, 0dh, '$';error message if number is too large

main:
dsp_msg:  mov ah, 09    ; screen display
      mov dx, msg   ; mov starting address of msg into dx 
      int 21h   ; display message

in_buff:      resb 20   ; reserve 20 bytes
      mov ah, 0ah   ; service read character
      mov dx, buffer ;move address of parameter block to dx
      int 21h   ;bios system call
      sub dx, 30h

chk_num:  
      cmp dx, '5'   ;compare entered nnumber to 5
      jge err   ;if entered value is greater or equal to 5 jump to err
      jb fin    ;if entered number is below 5 jump to fin

err:      mov ah, 09    ;
      mov dx, ermsg ;move ermsg to dx
      int 21h   ;display error message
      jmp in_buff     

fin:      int 20h

任何想法我做错了什么?

“更新:

我将代码更改为使用 01 函数
,但现在我不断收到错误消息“未指定操作大小”

我的新代码:

bits 16
org 0x100   ;start at offset 100
jmp main

buffer:   db 4  ; define 4 bytes
db 0    ; actual number of characters entered

msg: db "请输入 0 到 5 之间的数字", 0ah, 0dh, '$' ; 定义消息的字节

ermsg:    db "The number must be between 0 and 5", 0ah, 0dh, '$';error message if number is too large

main:
dsp_msg:  mov ah, 09    ; screen display
mov dx, msg ; mov starting address of msg into dx 
int 21h ; display message

in_buff:  resb 20   ; reserve 20 bytes
mov ah, 01  ; service read character
mov dx, buffer;move address of parameter block to dx
int 21h ;dos system call

chk_num:  
cmp [dx], 5 ;compare entered nnumber to 5
jge err ;if entered value is greater or equal to 5 jump to err
jb fin  ;if entered number is below 5 jump to fin

err:      mov ah, 09    ;
mov dx, ermsg   ;move ermsg to dx
int 21h ;display error message
jmp in_buff   

fin:      int 20h  

我正在使用 nasm 进行编译。有谁知道那是什么意思?
对不起所有的基本问题。这是我第一次处理汇编语言并发现它非常困难......

4

3 回答 3

1

您的代码包含:

sub dx, 30h

这从字符的 ASCII 代码中减去48(ASCII 0)。

但是您的代码也包含这一行:

cmp dx, '5'   ;compare entered nnumber to 5

它将字符的 ASCII 值与减去的值进行比较。

您使用的函数 ( 0x0A) 正在捕获缓冲输入,因此数据不会放置到DX,而是放在ES:DX。只需删除sub dx, 30h并且不比较寄存器值,而是那里的数据:

mov ah, 0ah   ; service read character
mov dx, buffer ;move address of parameter block to dx
int 21h       ;bios system call

chk_num:  
    cmp byte [es:dx+2], '5'   ;compare entered number to 5

顺便说一句,您将重写消息数据,因此您的缓冲区应如下所示:

buffer:   
    db 4  ;this buffer will be 4 bytes long
    db 0  ;well, we don't know how many characters are going to be entered, so `0` will be the best
    dd 0  ;and now the promised 4 bytes for buffer contents

您可能对可在此处找到的具体函数参考感兴趣。

于 2013-09-17T16:47:48.790 回答
0

在代码中间声明输入缓冲区可能不是一个好主意。把它放在你跳过的区域,或者放在section .bss.

int 21h/0Ah需要特殊格式化的缓冲区。第一个字节是接受的最大字符数。使其至少为 2,并且不超过缓冲区中实际留出的空间。第二个字节将包含实际输入的字符数。计数将包括结束输入的 CR...并且它将在缓冲区中。

输入的实际文本将从 开始[buffer + 2]。不幸[dx + 2]的是,它不是 16 位代码中的有效有效地址。使用bxsidi进行寻址。5和之间的区别'5'已经讲过了。

如果您想要的只是一个字符,您可能不需要“缓冲输入”中断。Ralf Brown 的中断列表是您的朋友!

于 2013-09-17T17:11:02.337 回答
0
  cmp dx, '5'   ;compare entered nnumber to 5

现在,由于5引用了 ,这可能只是与 ASCII 字符5(35H)比较,而不是与值 5 比较。

我很想删除那些引号。

于 2013-09-17T16:47:57.853 回答