Reputation: 1715
I'm trying to write an assembly language program that reads in a number and compares it to 5. If the number is less than 5 the program should end succesfuly else it should display an error message and prompt to input the number again. Whatever I do I don't seem to get it to end succesfully, it always jumps to the error label.
my code:
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
Any ideas what I'm doing wrong?
"UPDATE:
I changed my code to use the 01 function
but now I keep getting a error message "operation size not specified"
my new code:
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, 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
i'm using nasm to compile. does anyone know what that means?
Sorry for all the basic questions. this is the first time i'm dealing with assembly language and finding it quite difficult...
Upvotes: 0
Views: 1636
Reputation: 3119
Declaring your input buffer in the middle of code probably isn't a good idea. Put it in the area that you jump over, or in section .bss
.
The buffer for int 21h/0Ah
needs to be specially formatted. The first byte is the maximum number of characters to accept. Make it at least 2, and no more than what you've actually got room for in the buffer. The second byte will contain the number of characters actually entered. The count will include the CR that ends input... and it will be in the buffer.
The actual text entered will start at [buffer + 2]
. Unfortunately [dx + 2]
is not a valid effective address in 16-bit code. Use bx
, si
, or di
for addressing. The difference between 5
and '5'
has already been covered.
You probably don't need the "buffered input" interrupt if all you want is one character. Ralf Brown's Interrupt List is your friend!
Upvotes: 0
Reputation: 6413
Your code contains:
sub dx, 30h
This subtracts 48
(ASCII 0
) from ASCII code of character.
But your code also contains this line:
cmp dx, '5' ;compare entered nnumber to 5
Which compares ASCII value of character with value that was subtracted.
The function you use (0x0A
) is capturing buffered input, so data aren't placed to DX
, but on ES:DX
. Simply just remove sub dx, 30h
and don't compare register value, but data there:
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 you'll be rewriting data of message, so your buffer should look like this:
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
You may be interested in concrete function reference which can be found here.
Upvotes: 1
Reputation: 80203
cmp dx, '5' ;compare entered nnumber to 5
Now, since the 5
is quoted, this might just compare against the ASCII character 5
(35H) not against the value 5.
I'd bee sore tempted to remove those there quotes.
Upvotes: 0