Reputation: 3
im trying to program in assembler and i need to do something in order to wait for user input key (only enter or space) witout enter, like y/n options. I read about 16h in dos, its a sys_Call similar in linux? i also read about disabling canonization but look too complicated to the curse level thanks
section .bss
buffer resb 1
input resb 1
section .data
lineasConsola dd 3 ; Lineas (sin informacion) mostradas por defecto
lineasPantalla dd 3
lineasTotales dd 0
lineasContador dd 0
section .text
global _start
leerInput:
push ebx
push ecx
mov eax, 3 ; sys_read
mov ebx, 0
mov ecx, input
mov edx, 1
int 80h
pop ecx
pop ebx
ret
leerCaracter:
mov eax,3 ; sys_read
mov ecx,buffer
mov edx,1
int 80h
cmp eax,0 ;eof
je final
imprimirCaracter:
mov eax, 4 ; sys_write
push ebx ; Resguardo el manejador
mov ebx, 1
int 80h
pop ebx
cmp byte[buffer],10 ; Chequeo si llegue a fin de linea
jne leerCaracter
ret
imprimirLineasTotales
push ebx
push ecx
push edx
mov eax, 4
mov ebx, 1
mov ecx, [lineasTotales]
mov edx, 4
int 80h
pop edx
pop ecx
pop ebx
ret
avanzarLinea ; Actualiza los contadores para poder leer una linea mas
push ebx
mov ebx, [lineasConsola]
inc ebx
mov [lineasConsola], ebx
pop ebx
ret
avanzarPantalla ; Actualiza los contadores para poder leer una nueva pantalla
push ebx
mov ebx, [lineasConsola]
add ebx, lineasPantalla
mov [lineasConsola], ebx
pop ebx
ret
_start:
pop ebx ; argc
pop ebx ; argv[0]
pop ebx ; Nombre del archivo
mov eax,5 ; sys_open
mov ecx,0
int 80h
mov ebx,eax ; Muevo el puntero a ebx para leerlo
test eax,eax
js exite ; Se produjo un error al intentar abrir el archivo
leerLinea:
call leerCaracter ;imprimo una linea
push eax ; Llegue al final de la linea, debo aumentar la cantidad de lineas leidas y chequear si llegue al tope de la consola
push ebx
mov eax, [lineasTotales]
mov ebx, [lineasConsola]
inc eax ; Lei una linea
cmp eax, ebx ; Chequeo si complete la pantalla
mov [lineasTotales], eax
pop ebx
pop eax
jl leerLinea ; No llene la consola
;call imprimirLineasTotales ; Imprimir lineas leidas hasta el momento;no funciona
call leerInput
cmp byte[input],'s'
jne seguir ;no presione la barra
call avanzarLinea ; Usuario presiono la barra
jmp leerLinea
seguir:
cmp byte[input], 'e' ; Usuario presiono enter
jne exite ; No es la barar ni salto de linea, se produce un error
call avanzarPantalla
jmp leerLinea
mov ebx, 0 ; salgo sin errores
mov eax, 1 ; sys_exit
int 80h
final:
call imprimirLineasTotales
mov ebx, 0 ; salgo sin errores
mov eax, 1 ; sys_exit
int 80h
exite:
mov ebx, 6 ; If there was an error, save the errno in ebx
mov eax, 1 ; Put the exit syscall number in eax
int 80h ; Bail out
Upvotes: 0
Views: 2256
Reputation: 126140
By default, when reading from a terminal in Linux (which includes any terminal window or remote login, or any interactive thing with an actual keyboard involved), the kernel will collect the characters typed in a buffer, processing backspaces and the like, until a newline is entered. Only after the newline will it send the data back to the user process in response to a read system call. This is called "canonical" input processing. If you want to avoid this, and read single characters immediately as they are typed, you need to put the terminal in non-canonical mode. In C, you can do this with the tcsetattr(3) function in the C library, which you may be able to call from your assembly program. If you're trying to avoid even the C library however, you can use raw ioctl(2) system calls.
For linux, the necessary information is in the termios(3) and tty_ioctl(4) manual pages.
Upvotes: 1
Reputation: 191
Without changing the mode from canonical to non canonical mode, think this is not possible. This is because when user enter's a character, they get buffered inside kernel and, depending on the mode of the tty/console they get delivered to reader either before '\n' or immediately.
Upvotes: 0
Reputation:
Syscalls are what you're looking for, but without providing what you've tried, it's quite impossible to get into specifics of what you should be doing. Some general advice holds, though.
You can read one character at a time from terminal, which is just another file, using syscalls. Depending on the target architecture, namely the question is it 32- or 64-bit, you can find appropriate syscalls from unistd_32.h
or unistd_64.h
, most likely to lie in /usr/include/x86_64-linux-gnu/asm/
on your system.
The 32-bit syscalls take the syscall number in eax and arguments in ebx, ecx,edx, esi, edi and ebp. Setup those appropriately and do int 0x80.
The 64-bit syscalls take the syscall number rax and arguments in rdi, rsi, rdx, rcs, r8 and r9. Setup those appropriately and do syscall.
You might benefit from reading some other excellent Q&As on stackoverflow about assembly language programming on Linux. Actually, I think it could be taken as a recommended next step.
Upvotes: 0