NASM - The Netwide Assembler

NASM Forum => Example Code => Topic started by: TightCoderEx on June 10, 2012, 06:49:56 PM

Title: NON-CANONICAL
Post by: TightCoderEx on June 10, 2012, 06:49:56 PM
My implementation of single keystroke without echo.  In the course of developing these algos, I discovered for as far as I've gotten anyway, READ, WRITE & IOCTL don't differenciate between STDIN and STDOUT.

Previous state is an error.  If STDOUT = 1 is not used, redirection does not work

Preamble to application gets current settings
Code: [Select]
                enter 40, 0
                mov [Termios], rsp ; Save global copy of termios
               
        ; Read terminal parameters for toggle functionality

mov ax, TCGETS
mov rsi, rax
mov rdx, rsp               
        mov ax, SYS_IOCTL
        syscall
        push qword [rsp + 12] ; Permanent copy of defaults       

Postamble restores default, but if app craters before getting here, this may be a little mute
Code: [Select]
        ; Before we quit, make sure console get set back to defaults
       
        pop rax ; Get defaults
        cmp [rsp + 12], rax
        jz .Done ; Nothing to do, all is ok
       
        ; Set console back to its defaults
       
        mov [rsp + 12], rax
        xor rax, rax
        mov ax, TCSETS
mov rsi, rax
mov rdx, rsp               
        mov ax, SYS_IOCTL
        syscall       

This bit toggles mode off and on, so caller can leave in a certain mode for whatever time.
Code: [Select]
; =============================================================================================
; TOGGLE: Each call to toggle will turn canonical and echo off or on
; ---------------------------------------------------------------------------------------------
  Toggle:
 
  ; Maybe there could be a better way to nullify RAX, RSI & RDI
   
  xor rax, rax
  push rax
  pop rdi
  push rax
  pop rsi
mov si, TCSETS
mov al, SYS_IOCTL
mov rdx, [Termios] ; Get pointer to termios structure
xor word [rdx + 12], ICANON | ECHO
syscall  
  ret

I will have another version of this for menu selection probably with a switch and an array of pointers corresponding to A-Z let say
Code: [Select]
; =============================================================================================
; QUERY: Gets a single keystroke from operator that must be 'Y' or 'N', case insensitive

; ENTRY: RSI = Pointer to routines prompt string

; FLAGS:  ZF = 1 if "Yes", otherwise zero
; ---------------------------------------------------------------------------------------------
  Query:
  enter 4, 0
  call Console ; Display prompt associated with input
  call Toggle ; Switch to non-canonical, no echo
 
  ; Setup for getting single key input
 
  xor rdx, rdx
  mov dl, 1
  mov rsi, rsp
 
  ; Keep doing this until operator enters Y or N
 
  .Again call Keyboard ; Get response from operator
  mov al, [rsi]
  and al, 0x5f ; Get character and convert to uppercase
  cmp al, 'Y'
  jz .Done
  cmp al, 'N'
  jnz .Again
 
  inc al ; Bump so ZF = 0
 
  ; We've gotten a Y or N response and ZR has been set
 
        .Done pushf
                call Toggle
                popf
  leave
  ret

Needed to add preserving flags @ .Done