0

I recently make input using Linux assembly (x86_64) i got this code and i try it eventually the code are doesn't work like what i expected, i should wait a keystroke but it auto input from no where, i suspect termios flags... code are in below :

 ;Get current settings
    Mov  EAX, 16             ; SYS_ioctl
    Mov  EDI, 0              ; STDIN_FILENO
    Mov  ESI, 0x5401         ; TCGETS
    Mov  RDX, termios
    Int 80h

    And dword [c_cflag], 0xFD  ; Clear ICANON to disable canonical mode

    ; Write termios structure back
    Mov  EAX, 16             ; SYS_ioctl
    Mov  EDI, 0              ; STDIN_FILENO
    Mov  ESI, 0x5402         ; TCSETS
    Mov  RDX, termios
    Int 80h

    Mov EAX,0   ;sys_read kernel call
    Mov EBX,0   ;stdin trap (standart input)
    Mov ECX,Nada    ;Masukkan offset/jumlah byte yang akan di baca
    Mov EDX,1   ;Jumlah byte yang dibaca
    Int 80h     ;Call Kernel

for the termios struct :

SECTION .bss    ;deklarasi untuk variable yang belum terdefinisi

Enter: Resb 1   ;Pesan 1 byte untuk Enter
Nada: Resb 1
termios: 
    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 64      ; control characters

for the output :

nasm -f elf64 -g -F stabs key.asm
ld -o KeyPress key.o
./KeyPress
Untuk memulai tekan tombol enter: 
Tekan tombol untuk memainkan satu not: (1,2,3,4,5,6,7,8)
//this part are the error occur,i have to check if user inputed right value 
if not it will jump to error label and printed below message//
Error note not found please contact the app developer !!

reference : Linux Getch(), My Github Repo
PS: For the newest code i already push on my repository i use ubuntu 20.04 and Intel i7 (64-bit), thanks for the help

AFOEK
  • 37
  • 8
  • [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) - you can't use 64-bit addresses with `int 0x80`. Just don't use it at all in 64-bit code, but it makes `Mov RDX, termios` pointless vs. `EDX` – Peter Cordes Jul 22 '20 at 08:10

1 Answers1

3

... i got this code and i try it eventually the code are doesn't work like what i expected ...

   Mov  ESI, 0x5401
   Mov  RDX, termios
   Int  80h

This won't work:

Int 80h is the 32-bit system call used in 32-bit programs. The first three arguments are passed in EBX, ECX and EDX, and definitely not in ESI.

And the values of EAX required for Int 80h differ from the method used in 64-bit programs: read() would be EAX=3, not EAX=0.

Int 80h seems to work in 64-bit programs, too, however, passing 64-bit values wont work; so you cannot use Int 80h for system calls that take addresses (in the example: the address of termios) as argument.

Either you assemble and link your code as 32-bit program, use int 80h, pass the arguments in EBX, ECX and EDX and use the values in EAX required for 32-bit programs (for example: EAX=3 for read()):

mov eax, 54      ; sys_ioctl when using "int 80h"
mov ebx, 0       ; stdin
mov ecx, 0x5402  ; TCSETS
mov edx, termios
int 80h

Or you build a 64-bit program and use the syscall instruction to call system calls (see this question):

mov eax, 0    ; sys_read when using "syscall"
              ; note that this instruction will actually set RAX to 0
mov edi, 0    ; set RDI to stdin (implicitly sets rdi)
mov rsi, Nada ; Address of the buffer (see below)
              ; we explicitly have to use "rsi" here!
mov edx, 1    ; number of bytes
syscall
mov ecx, Nada

I don't use "nasm" but another assembler; so maybe I am wrong. But as far as I know the instruction above would be interpreted by "nasm" as:

Read the value stored in the RAM at the address Nada and write that value to the ecx register.

However, you want the address of Nada to be written to the ecx register.

As far as I know, this instruction would be written as: mov ecx, offset Nada in "masm".

If this is true, the corresponding line in my example above must be: mov rsi, offset Nada.

And dword [c_cflag], 0xFD  ; Clear ICANON to disable canonical mode

This line contains two errors:

ICANON is located in C_LFLAG, not in C_CFLAG.

And this instruction would be identical to the C/C++ instruction: c_cflag &= ~0xFFFFFF02, but you want to do: c_cflag &= ~2.

To clear bit 1 only, you have two possibilities:

And byte [c_lflag], 0xFD
; OR:
And dword [c_lflag], 0xFFFFFFFD
Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • thanks for the help @Martin Rosenau, but i doesn't understand on ```c_lflag``` for... for the clear to bit i must ```And``` it twice? – AFOEK Jul 22 '20 at 06:27
  • for the ```read()``` i must place it before i clear the termios structure back or after i clear it ? – AFOEK Jul 22 '20 at 06:30
  • @felixmontalfu No, you have to do `AND` only once. However, there are two different variants and you chose one of the two variants. – Martin Rosenau Jul 22 '20 at 07:06
  • @felixmontalfu Typically (when programming in C) I use the following order: Read termios; write termios; use `read()`; write the old value of termios. If you don't restore termios to the old value, the shell will get problems after your program finished. – Martin Rosenau Jul 22 '20 at 07:08
  • ahhh so the order is already right ? and just some argument error ? @Martin Rosenau – AFOEK Jul 22 '20 at 07:52
  • Btw the keystroke result are stored in what registers? ```EAX```, ```EBX```, or ```EDX``` ? because i want to compare it to check the keystroke are listed or not – AFOEK Jul 22 '20 at 08:00
  • the code are working but it still capture wrong value from the keystroke... i tried to compare the keystroke result i believe its stored in ```ECX``` like this ```Cmp ECX,49``` Did i do something wrong ? – AFOEK Jul 22 '20 at 12:11
  • @felixmontalfu The `read()` function reads (up to) `edx` bytes (not: keystrokes) to the memory at the address `ecx`. On success, `eax` contains the number of bytes read. In your case this means: If `eax=1` after the system call, the memory at the address `Nada` contains one byte read; otherwise no data has been read. Note that there are some keys (for example the cursor keys) that will send multiple bytes. Your program would detect this as multiple key presses... – Martin Rosenau Jul 22 '20 at 14:24
  • so for the keystroke value are in ```EAX```? but some say it only store return value only like you said... i stilll confuse in there... :( . I assume like 16 bit if i read using ```AH,0h``` the keystroke are stored in ```BL```.... – AFOEK Jul 22 '20 at 15:09
  • @felixmontalfu You are confusing the `getch()` function with the `read()` function: The `getch()` function is not a built-in kernel function but a function written in C or assembly that calls the `read()` function... – Martin Rosenau Jul 22 '20 at 15:14
  • OK then, if i want to know the keystroke what i inputted i just compare ```[Nada] ```? I already try it but it's not work like i expected.... btw i tried to compare like this ```Cmp byte [Nada],0x49``` thanks :) – AFOEK Jul 24 '20 at 04:09