Question

I'm trying to port my stdrepl library to FASM for learning purposes. I know that the GNU readline library already does what I'm trying to do, but I want to learn how to write non-trivial programs in assembly.

In node.js I can easily create a tty by writing:

var stdin = process.stdin;
stdin.setEncoding("utf8");
stdin.setRawMode(true);
stdin.resume();

How do I achieve the same results in pure assembly. I tried reading one byte from stdin at a time in a loop as follows, but it doesn't return the byte right after I hit a key:

oct db ?

mov eax, 3
xor ebx, ebx
mov ecx, oct
mov edx, 1

Note that the data definition oct is not a part of the loop, so please don't smite me for that. I know how to structure an assembly program.

Was it helpful?

Solution

Sorry for the delay (I really should "register" here - that'll get me "notifications", right?). As I said, it's rudimentary and imperfect. Some of the "usual" stuff may be defined elsewhere, but I think you can figure out how to get it to assemble. Just call it - no parameters - and the key is returned in al. Hope it's some use to you!

;-----------------------------
; 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, __NR_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, __NR_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, __NR_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, __NR_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
;-------------------------

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top