Author Topic: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working  (Read 15046 times)

Offline RaenirS

  • Jr. Member
  • *
  • Posts: 8
Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« 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.

Code: [Select]
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.

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #1 on: March 04, 2013, 06:24:14 PM »
You are comparing the address of aChar with your value:

Code: [Select]
    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:

Code: [Select]
    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...

Offline RaenirS

  • Jr. Member
  • *
  • Posts: 8
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #2 on: March 04, 2013, 06:33:35 PM »
It still isn't evaluating:

Code: [Select]
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

Quote
[poise] [/home/myusername/afolder/foldception] > ./cccc
Enter a character:
5
Bigger

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #3 on: March 04, 2013, 07:14:51 PM »
In your code:

This reserves 2 bytes, not 10:
Code: [Select]
aChar resb 2 ; reserve 10 bytes for aChar


When reading input, specify number of bytes to read in edx:
Code: [Select]
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

Offline RaenirS

  • Jr. Member
  • *
  • Posts: 8
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #4 on: March 04, 2013, 07:33:37 PM »
I did the changes but it still doesn't work, no difference in out put aside from an extra line now.

Code: [Select]
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

Quote
[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.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #5 on: March 04, 2013, 07:50:06 PM »
Code: [Select]
; ...
; 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...

Code: [Select]
    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:
Code: [Select]
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.
Code: [Select]
mov al, [aChar]
cmp al, '0'
jb smaller
cmp al, '9'
ja bigger
; it's a character representing a digit
;...

Quote
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'.

Quote
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...

Offline RaenirS

  • Jr. Member
  • *
  • Posts: 8
Re: Parsing ASCII, CMP Evaluation of ASCII with HEX Not Working
« Reply #6 on: March 04, 2013, 08:19:03 PM »
I think so, it certainly looks more elegant, here's what has so far worked.

Code: [Select]
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.
« Last Edit: March 04, 2013, 08:31:23 PM by RaenirS »