Reputation: 576
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
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