我正在尝试编写一个读取数字的汇编语言程序,并将其与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进行编译。有谁知道这意味着什么?
对不起,所有的基本问题。这是我第一次使用汇编语言并发现它非常困难......
答案 0 :(得分: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
BTW你将重写消息数据,所以你的缓冲区应该是这样的:
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
您可能对可以找到的具体功能参考感兴趣here。
答案 1 :(得分:0)
cmp dx, '5' ;compare entered nnumber to 5
现在,由于5
被引用,这可能只是与ASCII字符5
(35H)进行比较,而不是与值5进行比较。
我很想去除那些引号。
答案 2 :(得分:0)
在代码中间声明输入缓冲区可能不是一个好主意。把它放在你跳过的区域,或section .bss
。
int 21h/0Ah
的缓冲区需要特殊格式化。第一个字节是要接受的最大字符数。使它至少为2,并且不超过你在缓冲区中实际获得的空间。第二个字节将包含实际输入的字符数。计数将包括结束输入的CR ......它将在缓冲区中。
输入的实际文字将从[buffer + 2]
开始。不幸的是,[dx + 2]
不是16位代码中的有效有效地址。使用bx
,si
或di
进行寻址。 5
和'5'
之间的区别已经包含在内。
如果你想要的只是一个字符,你可能不需要“缓冲输入”中断。拉尔夫布朗的中断名单是你的朋友!