NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: RaenirS on March 04, 2013, 03:08:57 PM
-
Basically I have to write a program where the user keeps inputting a single character which we evaluate to being decimal, control key, upper case, lower case, symbols etc.
So Looking around I've found some code but it doesn't work. What I am trying to do is taking an ASCII character, and hopefully comparing its HEX value with either 30h or 39h (0 or 9), if its less than 30h than its Something(tm) if its Greater Than 9 It is Something Else(tm), if neither than its clearly a decimal and I can output a message saying so.
However it doesn't seem to work.
segment .data
msg db 'Enter a character: ', 0xA ; text message
len equ $-msg ; length of msg
msg2 db 'Your character is: ' ; text message
len2 equ $-msg2
smallerKey: db "Smaller", 10
smallerLen: equ $-smallerKey
biggerKey: db "Bigger", 10
biggerLen: equ $-biggerKey
segment .bss
;
aChar resb 2 ; reserve 10 bytes for aChar
segment .text
global _start
_start:
; ### Code for Outputting a simple Message ###
mov eax, 4 ; select kernal call #4
mov ebx, 1 ; default output device
mov ecx, msg ; second argument; pointer to message
mov edx, len ; third argument: length
int 0x80 ; invoke kernal call to write
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
int 0x80 ; invoke kernal call to read
decimal:
mov ebx, 30h ; smallest decimal ASCII
mov edx, aChar
cmp edx, ebx
jl smaller
mov ebx, 39h ; smallest decimal ASCII
mov edx, aChar
cmp edx, ebx
jg bigger
jmp exit
smaller: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, smallerKey
mov edx, smallerLen
int 0x80
bigger: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, biggerKey
mov edx, biggerLen
int 0x80
exit:
mov eax, 1
xor ebx, ebx
int 0x80
Here's my code broken down as simple of possible for testing purposes. The code keeps on evaluating that '5' is bigger than 39h and keeps jumping to the "is bigger" label.
I assume its correct that they are evaluating each other as HEX, otherwise I would get an invalid opcode/operant error right? So *what* is '5' showing up as? I'm completely lost without an IDE, which are neither non existent or don't work on modern computers.
-
You are comparing the address of aChar with your value:
mov edx, aChar ;<--- this means to load edx with the address of aChar!!!
cmp edx, ebx
You want to compare the value pointed at by aChar:
mov eax, aChar ;<--- load the address of aChar into eax
mov edx, [eax] ; <--- copy the value pointed at by eax to edx ( notice the [] brackets )
cmp edx, ebx
That should help you move forward...
-
It still isn't evaluating:
segment .data
msg db 'Enter a character: ', 0xA ; text message
len equ $-msg ; length of msg
msg2 db 'Your character is: ' ; text message
len2 equ $-msg2
smallerKey: db "Smaller", 10
smallerLen: equ $-smallerKey
biggerKey: db "Bigger", 10
biggerLen: equ $-biggerKey
segment .bss
;
aChar resb 2 ; reserve 10 bytes for aChar
segment .text
global _start
_start:
; ### Code for Outputting a simple Message ###
mov eax, 4 ; select kernal call #4
mov ebx, 1 ; default output device
mov ecx, msg ; second argument; pointer to message
mov edx, len ; third argument: length
int 0x80 ; invoke kernal call to write
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
int 0x80 ; invoke kernal call to read
decimal:
mov ebx, 30h ; smallest decimal ASCII
mov edx, aChar
cmp [edx], ebx
jl smaller
mov ebx, 39h ; smallest decimal ASCII
mov edx, aChar
cmp [edx], ebx
jg bigger
jmp exit
smaller: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, smallerKey
mov edx, smallerLen
int 0x80
bigger: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, biggerKey
mov edx, biggerLen
int 0x80
exit:
mov eax, 1
xor ebx, ebx
int 0x80
[poise] [/home/myusername/afolder/foldception] > ./cccc
Enter a character:
5
Bigger
-
In your code:
This reserves 2 bytes, not 10:
aChar resb 2 ; reserve 10 bytes for aChar
When reading input, specify number of bytes to read in edx:
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
mov edx, 1 ;<--- specify the number of bytes to read in edx
int 0x80 ; invoke kernal call to read
-
I did the changes but it still doesn't work, no difference in out put aside from an extra line now.
segment .data
msg db 'Enter a character: ', 0xA ; text message
len equ $-msg ; length of msg
msg2 db 'Your character is: ' ; text message
len2 equ $-msg2
smallerKey: db "Smaller", 10
smallerLen: equ $-smallerKey
biggerKey: db "Bigger", 10
biggerLen: equ $-biggerKey
segment .bss
;
aChar resb 2 ; reserve 10 bytes for aChar
segment .text
global _start
_start:
; ### Code for Outputting a simple Message ###
mov eax, 4 ; select kernal call #4
mov ebx, 1 ; default output device
mov ecx, msg ; second argument; pointer to message
mov edx, len ; third argument: length
int 0x80 ; invoke kernal call to write
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
mov edx, 1 ; <--- specify the number of bytes to read in edx
int 0x80 ; invoke kernal call to read
decimal:
mov ebx, 30h ; smallest decimal ASCII
mov edx, aChar
cmp [edx], ebx
jl smaller
mov ebx, 39h ; smallest decimal ASCII
mov edx, aChar
cmp [edx], ebx
jg bigger
jmp exit
smaller: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, smallerKey
mov edx, smallerLen
int 0x80
bigger: ; Tell that it's a printable symbol
mov eax, 4
mov ebx, 1
mov ecx, biggerKey
mov edx, biggerLen
int 0x80
exit:
mov eax, 1
xor ebx, ebx
int 0x80
[poise] [/home/b/b_bradl/comp228/Assignment2] > ./cccc
Enter a character:
5
Bigger
[poise] [/home/b/b_bradl/comp228/Assignment2] >
[poise] [/home/b/b_bradl/comp228/Assignment2] > cursor is here
Or was that line also meant to go under decimal?
Changing aChar's resb to 8 or 10 doesn't seem to make any different though.
-
; ...
; reading character from keyboard...
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
; what's edx here?
; you don't want to read more than your buffer length!
int 0x80 ; invoke kernal call to read
decimal:
mov ebx, 30h ; smallest decimal ASCII
; as Rob points out, here's your problem
mov edx, aChar ; address(!) of buffer
Rob suggests...
mov eax, aChar ;<--- load the address of aChar into eax
mov edx, [eax] ; <--- copy the value pointed at by eax to edx ( notice the [] brackets )
cmp edx, ebx
However... we're moving four bytes into edx from your buffer. Your buffer is only defined as two bytes (comment does not match code!), and we're only interested in one of 'em.
We could do:
movxz edx, byte [aChar] ; or use a register
... but I think it might be simpler to use 8-bit registers to compare and manipulate characters - since that's what size they are.
mov al, [aChar]
cmp al, '0'
jb smaller
cmp al, '9'
ja bigger
; it's a character representing a digit
;...
I assume its correct that they are evaluating each other as HEX,
Actually they're just bit patterns. "HEX" is a way of representing a number. It's the same number (bit pattern) regardless of whether we call it "48" or "30h" or "00110000b" or "060q". For printable characters, I think it's most "readable" if we just call it '0'.
I'm completely lost without an IDE, which are neither non existent or don't work on modern computers.
Jeff Owens has written an IDE for Linux. He has abandoned the project, AFAIK, but it is still quite useful! I'm a "command line guy" and don't much crave an IDE, but the "pop up help" is excellent - the Nasm Manual, system calls, other stuff - the best I've found! There's a lot of stuff besides the IDE in this package... much of which I don't find useful, to be honest. There's a debugger - couple of them, actually - which you might find easier to use than gdb, and which will probably be more help at solving this kind of problem than the IDE itself. (by rights, we really ought to learn to use gdb - I plan to do so some day soon :) )
http://home.myfairpoint.net/fbkotler/asmtools-0.9.69.tar.gz
I know Jeff would be pleased if more people were using his stuff!
Best,
Frank
Edit: You guys have made several posts while I was writing my one... but I think it's still relevant...
-
I think so, it certainly looks more elegant, here's what has so far worked.
segment .data
msg db 'Enter a character: ', 0xA ; text message
len equ $-msg ; length of msg
msg2 db 'Your character is: ' ; text message
len2 equ $-msg2
smallerKey: db "Smaller", 10
smallerLen: equ $-smallerKey
biggerKey: db "Bigger", 10
biggerLen: equ $-biggerKey
segment .bss
;
aChar resb 8 ; reserve 8 bytes for aChar
; I changed the above to 8 and that seems to work with the code below,
; I don't know if its crucial to its execution.
segment .text
global _start
_start:
; ### Code for Outputting a simple Message ###
mov eax, 4 ; select kernal call #4
mov ebx, 1 ; default output device
mov ecx, msg ; second argument; pointer to message
mov edx, len ; third argument: length
int 0x80 ; invoke kernal call to write
mov eax, 3 ; select kernal call #3
mov ebx, 0 ; default input device
mov ecx, aChar ; pointer to aChar'
; mov edx, 1 ; <--- specify the number of bytes to read in edx
; the above line just ends up acting as an escape character and acts as if I hit "enter", don't know why!
int 0x80 ; invoke kernal call to read
decimal:
mov ebx, 30h ; smallest decimal ASCII
mov edx, [aChar] ; // LOADS DATA. HERE IS WHERE JUNK DATA APPEARS
mov ecx, 000000FF ;
and edx, ecx; // THIS WOULD ELIMINATE THE JUNK DATA.
cmp edx, ebx
jl smaller
mov ebx, 39h ; smallest decimal ASCII
; // You don't need to load edx twice.
cmp edx, ebx
jg bigger
jmp exit
smaller: ; Tell that it's smaller
mov eax, 4
mov ebx, 1
mov ecx, smallerKey
mov edx, smallerLen
int 0x80
jmp exit ; because duh
bigger: ; Tell that it's a bigger
mov eax, 4
mov ebx, 1
mov ecx, biggerKey
mov edx, biggerLen
int 0x80
exit:
mov eax, 1
xor ebx, ebx
int 0x80
What someone else had suggested to me was to "purge" the excess bits that were fudging my numbers, I'll attempt your method as I think its probably more elegant.
Edit3: Derp, forgot the square brackets, now it works! 8)
edit4: heh, forum doesn't like unicode, irony.