Author Topic: Handling Keystrokes in Assembly?  (Read 9940 times)

Offline tarek89

  • Jr. Member
  • *
  • Posts: 20
Handling Keystrokes in Assembly?
« on: June 28, 2011, 12:05:29 PM »
Hello there,

I have a question not related with nasm itself, it is an Assembly language question (Linux assembly)
i wand to handle keystrokes during runtime, for example same like (VI) editor, i want to execute certain type of lines when user hit ESC key without pressing enter in standard input
how can i get it?!
« Last Edit: June 28, 2011, 12:27:59 PM by tarek89 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Handling Keystrokes in Assembly?
« Reply #1 on: June 28, 2011, 02:30:35 PM »
Yeah, we can do that. It isn't easy! This is what I use:

Code: [Select]
;-----------------------------
; ioctl subfunctions
%define TCGETS 0x5401 ; tty-"magic"
%define TCSETS 0x5402

; flags for 'em
%define ICANON 2 ;.Do erase and kill processing.
%define ECHO 8 ;.Enable echo.


    struc termios
alignb 4
.c_iflag: resd 1 ; input mode flags
.c_oflag: resd 1 ; output mode flags
.c_cflag: resd 1 ; control mode flags
.c_lflag: resd 1 ; local mode flags
.c_line: resb 1 ; line discipline
.c_cc: resb 19 ; control characters
    endstruc
;---------------------------------

getc:
    push ebp
    mov ebp, esp
   
    sub esp, termios_size     ; make a place for current kbd mode
   
    push edx
    push ecx
    push ebx
   
    mov eax, SYS_IOCTL        ; get current mode
    mov ebx, STDIN
    mov ecx, TCGETS
    lea edx, [ebp - termios_size]
    int 80h
   
                              ; monkey with it
    and dword [ebp - termios_size + termios.c_lflag], ~(ICANON | ECHO)

    mov eax, SYS_IOCTL
    mov ebx, STDIN
    mov ecx, TCSETS
    lea edx, [ebp - termios_size]
    int 80h
   
    xor eax, eax
    push eax         ; this is the buffer to read into
     
    mov eax, SYS_READ
    mov ebx, STDIN
    mov ecx, esp     ; character goes on the stack
    mov edx, 1       ; just one
    int 80h          ; do it
                     
                     ; restore normal kbd mode
    or dword [ebp - termios_size + termios.c_lflag], ICANON | ECHO
   
    mov eax, SYS_IOCTL 
    mov ebx, STDIN
    mov ecx, TCSETS
    lea edx, [ebp - termios_size]
    int 80h
   
    pop eax          ; get character into al

    pop ebx          ; restore caller's regs
    pop ecx
    pop edx
   
    mov esp, ebp     ; leave
    pop ebp
    ret
;-------------------------

This leaves a lot to be desired! It really needs two termios structures on the stack, one to "get" into, and one to "set" from. This poor routine ASSumes we know how stdin was configured when we got it. It can also be broken by suspending the program with control-z and restarting it with "fg". It works okay for what I need. For your purposes, you might want to "fix" stdin, and leave it that way for the duration of the program, rather than swap back and forth for each keystroke, as I do.

For Windows users, look into "SetConsoleMode" for similar purposes...

All rather a PITA, just to get a key, but that's the only way I know to do it.

Best,
Frank


Offline tarek89

  • Jr. Member
  • *
  • Posts: 20
Re: Handling Keystrokes in Assembly?
« Reply #2 on: June 28, 2011, 02:51:16 PM »
Yea i got it, that was a great idea thank you alot..

So how could i make a generic function prints out the content of a register as it is
for example eax contains 2399 i wanna print it as it is on screen

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Handling Keystrokes in Assembly?
« Reply #3 on: June 28, 2011, 05:41:20 PM »
I just posted a "quickie" method in a thread under "example code", so I'll refer you to that thread rather than "dilute" this one with something other than "handling keystrokes". Hopeless to expect "one thread, one topic" (I just "diluted" that one), but we could try...

Brethren has posted a different method, as well, under "example code" and I'll be posting another method or two... when/if I get to it...

Best,
Frank


Offline Mathi

  • Jr. Member
  • *
  • Posts: 82
  • Country: in
    • Win32NASM
Re: Handling Keystrokes in Assembly?
« Reply #4 on: June 28, 2011, 05:48:25 PM »
To print the content of registers, you might first need to convert it to string.
Then use the sys_write system call to display the string on to the screen.

I usually do a macro call, int2str (Utils.mac attached).

You can write it as a separate procedure and do some customization to print all registers, or selected registers based on parameter passed.

Code: [Select]
%include "Utils.inc"

section .data
somedata dd 0 ;; Not needed in this program.                                    
section .bss
buffer resb 32  ;;reserve some bytes to store the number in string format.

section .text
global _start

_start:

mov eax,12345
;;;;;START PRINT EAX;;;;;
int2str eax,buffer   ; convert eax ( integer) to string and store in buffer.

mov eax,4            ; The system call for write (sys_write)
mov ebx,1            ; File descriptor 1 - standard output
mov ecx,buffer       
     ; edx is already setup with the number of characters to write. (by int2str macro).   
                     
int 80h              ;; Should write "12345" on the screen.
;;;;;END PRINT EAX;;;;;

mov eax,1            ;; exit system call.
mov ebx,0           
int 80h

Offline tarek89

  • Jr. Member
  • *
  • Posts: 20
Re: Handling Keystrokes in Assembly?
« Reply #5 on: June 28, 2011, 06:20:52 PM »
Thank you alot, i was trying to make such a function but i got deadlocked while figuring out the algorithm
but now you saved me =)
Thanks alot