RaenirSalazar
RaenirSalazar

Reputation: 576

NASM Parsing Ascii Characters to display

Essentially what I wish to do (this is for an assignment) is have the user type in a character, and then display whether its an upper case/lower case letter, a 0-9 decimal, printable symbol, or a control key.

Unfortunately while the documentation gives me an idea as to fiddle with the control logic (if/else, loops, etc) actually knowing the commands to get NASM to do what I want it to do has been frustrating as the slides and class notes, and the documentation has not been entirely constructive.

Control Keys I believe are esc, null, tab, etc from DEC 0 to 32.

In my code below, I accept input from the user, but I don't think it accepts control keys, how would I fiddle it to do so?

segment .data

    msg3 dw '10h'
segment .bss
;
aChar resb 2 ; reserve 10 bytes for aChar

segment .text
    global _start
_start:


    ; ### Code for simple Input ###
    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   


    ; ### Code to spit the input to the screen ###
    mov eax, 4 ; select kernal call #4
    mov ebx, 1      ; default output device
    mov ecx, aChar ; pointer to ID
    int 0x80 ; write id read

    ; termination code
exit: mov ax, 1 ; select system call #1 system exit
    mov bx, 0 ; 0 means normal
    int 0x80 ; invoke kernal call

So what I am thinking, assuming I am able to accept control keys in ascii. Is that once a user inputs a character, I convert it to hex or decimal, whichever is easier and then run if else cases wherein if its between certain values its an X, and then display X, if its between 2 different values its an Y and so on.

Since something less than 33 is clearly a control key I think, (is DEL a control key? Its DEC 127), but anything less than 48 is a symbol I think, but it also has to be more than 32, or do I just implicitly assume if it greater than 32, but less than 48, assume symbol? Annoying how everything seems to inhabit different portions of the ASCII chart.

Here's the code for converting ASCII to HEX, I think decimal might've been easier to work with, but I have no idea how to a) figure out even if I have binary value of the ascii character in a registry somewhere and b) convert it to decimal so since I have this code might as well use it?

;Hex equivalent of characters              HEX2CHAR.ASM
;
;        Objective: To print the hex equivalent of
;                   ASCII character code. Demonstrates
;                   the use of xlat instruction.
;            Input: Requests a character from the user.
;           Output: Prints the ASCII code of the
;                   input character in hex.
%include "io.mac"

.DATA
char_prompt    db  "Please input a character: ",0
out_msg1       db  "The ASCII code of '",0
out_msg2       db  "' in hex is ",0
query_msg      db  "Do you want to quit (Y/N): ",0
; translation table: 4-bit binary to hex
hex_table      db  "0123456789ABCDEF"    

.CODE
     .STARTUP
read_char:
     PutStr  char_prompt  ; request a char. input
     GetCh   AL           ; read input character

     PutStr  out_msg1
     PutCh   AL
     PutStr  out_msg2
     mov     AH,AL        ; save input character in AH
     mov     EBX,hex_table; EBX = translation table
     shr     AL,4         ; move upper 4 bits to lower half
     xlatb                ; replace AL with hex digit
     PutCh   AL           ; write the first hex digit
     mov     AL,AH        ; restore input character to AL
     and     AL,0FH       ; mask off upper 4 bits
     xlatb
     PutCh   AL           ; write the second hex digit
     nwln
     PutStr  query_msg    ; query user whether to terminate
     GetCh   AL           ; read response

     cmp     AL,'Y'       ; if response is not 'Y'
     jne     read_char    ; read another character
done:                        ; otherwise, terminate program
     .EXIT

From "Guide to Assembly Programming in Linux".

My query is, if the code converts it to hex, is it actually in memory as hex somewhere? Or is it just displayed as ascii character representation of the hex? That obviously doesn't help me if so.

So my questions are in order:

1.How do I accept user input of a control key. 2. How do I parse ascii so that I have in memory register somewhere which I suppose is a fancy way of saying "variable" the HEX value of the ASCII character I typed in? Which I can then fiddle with and evaluate to display what I need to display?

edit: I think I found a solution, the problem is it doesn't work and I don't know why:

decimal: 
    mov ebx, 30h    ; smallest decimal ASCII 
    mov edx, key
    cmp edx, ebx
    jl  uppercase
    mov ebx, 39h    ; test against 9
    cmp edx, ebx
    jg  exit
    mov eax, 4
    mov ebx, 1
    mov ecx, decimalKey
    mov edx, decimalLen
    int 0x80

It just jumps to "exit" evaluating as "greater than" each time, no matter what I input.

Upvotes: 3

Views: 5334

Answers (1)

RaenirSalazar
RaenirSalazar

Reputation: 576

Figured it out finally.

;
; This is assignment 2, it takes key strokes from the user
; and displays whether it is a control key, upper case,
; lower case, a printable symbol, or a decimal.
; By Blayne Elison Bradley, 9688994
; March 4th 2013

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   

    controlKey: db "Control Key", 10
    controlLen: equ $-controlKey

    control2Key: db "ControlKey2", 10
    control2Len: equ $-control2Key

    printableKey: db "Printable", 10
    printableLen: equ $-printableKey

    printable2Key: db "Printable-2", 10
    printable2Len: equ $-printable2Key

    printable3Key: db "Printable-3", 10
    printable3Len: equ $-printable3Key

    printable4Key: db "Printable-4", 10
    printable4Len: equ $-printable4Key

    decimalKey: db "Decimal", 10
    decimalLen: equ $-decimalKey

    upperKey: db "Upper Case", 10
    upperLen: equ $-upperKey

    lowerKey: db "Lower Case", 10
    lowerLen: equ $-lowerKey

    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'
    int 0x80 ; invoke kernal call to read

control: ; is it a control key?
    mov al,  [aChar] ; 
    cmp al, 1Fh
    jg  printable

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, controlKey
    mov edx, controlLen
    int 0x80
    jmp exit ; because duh

decimal:    
    mov al,  [aChar] ; 
    cmp al, '9'
    jg  printable2

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, decimalKey
    mov edx, decimalLen
    int 0x80    
    jmp exit

printable:
    mov al,  [aChar] ; 
    cmp al, '/'
    jg  decimal

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, controlKey
    mov edx, controlLen
    int 0x80
    jmp exit ; because duh

printable2:
    mov al,  [aChar] ; 
    cmp al, '@'
    jg  uppercase

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, printable2Key
    mov edx, printable2Len
    int 0x80
    jmp exit ; because duh

uppercase:  
    mov al,  [aChar] ; 
    cmp al, 'Z'
    jg printable3

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, upperKey
    mov edx, upperLen
    int 0x80
    jmp exit ; because duh

printable3:
    mov al,  [aChar] ; 
    cmp al, '`'
    jg  lowercase

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, printable3Key
    mov edx, printable3Len
    int 0x80
    jmp exit ; because duh

lowercase:
    mov al,  [aChar] ; 
    cmp al, 7Ah
    jg  printable4

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, lowerKey
    mov edx, lowerLen
    int 0x80
    jmp exit ; because duh

printable4:
    mov al,  [aChar] ; 
    cmp al, '~'
    jg  control2

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, printable4Key
    mov edx, printable4Len
    int 0x80
    jmp exit ; because duh

control2: ; is it a control key?
    mov al,  [aChar] ; 
    cmp al, 7Fh
    jg  exit ; beyond range

    ; Output
    mov eax, 4
    mov ebx, 1
    mov ecx, control2Key
    mov edx, control2Len
    int 0x80
    jmp exit ; because duh

exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80

Upvotes: 2

Related Questions