Linux temios 非规范 sys_call getch() 不工作
Linux temios non-canonical sys_call getch() doesn't work
我最近使用 Linux 程序集 (x86_64) 进行输入,我得到了这段代码并尝试了它,最终代码并不像我预期的那样工作,我应该等待击键但是它从任何地方自动输入,我怀疑 termios 标志...代码在下面:
;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
对于 termios 结构:
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
对于输出:
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 !!
参考:, My Github Repo
PS:对于我已经推送到我的存储库的最新代码,我使用 ubuntu 20.04 和 Intel i7(64 位),感谢您的帮助
... 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
这行不通:
Int 80h
是32位程序中使用的32位系统调用。前三个参数在EBX
、ECX
和EDX
中传递,在ESI
中肯定是而不是。
并且 Int 80h
所需的 EAX
的值与 64 位程序中使用的方法不同:read()
将是 EAX=3
,而不是 EAX=0
.
Int 80h
似乎也适用于 64 位程序,但是,传递 64 位值将不起作用;因此您不能将 Int 80h
用于以地址(在示例中:termios
的地址)作为参数的系统调用。
要么你 assemble 和 link 你的代码作为 32 位程序,使用 int 80h
,传递 EBX
、ECX
和 EDX
并使用 32 位程序所需的 EAX
中的值(例如:EAX=3
用于 read()
):
mov eax, 54 ; sys_ioctl when using "int 80h"
mov ebx, 0 ; stdin
mov ecx, 0x5402 ; TCSETS
mov edx, termios
int 80h
或者您构建一个 64 位程序并使用 syscall
指令调用系统调用(参见 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
我不使用“nasm”而是另一个assembler;所以也许我错了。但据我所知,上面的指令将被“nasm”解释为:
读取存储在 RAM 地址 Nada
的值,并将该值写入 ecx
寄存器。
但是,您希望将Nada
的地址写入ecx
寄存器。
据我所知,这条指令应该写成:mov ecx, offset Nada
in "masm".
如果这是真的,我上面例子中对应的行必须是:mov rsi, offset Nada
.
And dword [c_cflag], 0xFD ; Clear ICANON to disable canonical mode
这一行包含两个错误:
ICANON
位于 C_LFLAG
,而不是 C_CFLAG
。
此指令与 C/C++ 指令相同:c_cflag &= ~0xFFFFFF02
,但您要执行的操作是:c_cflag &= ~2
.
要仅清除位 1,您有两种可能性:
And byte [c_lflag], 0xFD
; OR:
And dword [c_lflag], 0xFFFFFFFD
我最近使用 Linux 程序集 (x86_64) 进行输入,我得到了这段代码并尝试了它,最终代码并不像我预期的那样工作,我应该等待击键但是它从任何地方自动输入,我怀疑 termios 标志...代码在下面:
;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
对于 termios 结构:
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
对于输出:
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 !!
参考:
PS:对于我已经推送到我的存储库的最新代码,我使用 ubuntu 20.04 和 Intel i7(64 位),感谢您的帮助
... 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
这行不通:
Int 80h
是32位程序中使用的32位系统调用。前三个参数在EBX
、ECX
和EDX
中传递,在ESI
中肯定是而不是。
并且 Int 80h
所需的 EAX
的值与 64 位程序中使用的方法不同:read()
将是 EAX=3
,而不是 EAX=0
.
Int 80h
似乎也适用于 64 位程序,但是,传递 64 位值将不起作用;因此您不能将 Int 80h
用于以地址(在示例中:termios
的地址)作为参数的系统调用。
要么你 assemble 和 link 你的代码作为 32 位程序,使用 int 80h
,传递 EBX
、ECX
和 EDX
并使用 32 位程序所需的 EAX
中的值(例如:EAX=3
用于 read()
):
mov eax, 54 ; sys_ioctl when using "int 80h"
mov ebx, 0 ; stdin
mov ecx, 0x5402 ; TCSETS
mov edx, termios
int 80h
或者您构建一个 64 位程序并使用 syscall
指令调用系统调用(参见 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
我不使用“nasm”而是另一个assembler;所以也许我错了。但据我所知,上面的指令将被“nasm”解释为:
读取存储在 RAM 地址 Nada
的值,并将该值写入 ecx
寄存器。
但是,您希望将Nada
的地址写入ecx
寄存器。
据我所知,这条指令应该写成:mov ecx, offset Nada
in "masm".
如果这是真的,我上面例子中对应的行必须是:mov rsi, offset Nada
.
And dword [c_cflag], 0xFD ; Clear ICANON to disable canonical mode
这一行包含两个错误:
ICANON
位于 C_LFLAG
,而不是 C_CFLAG
。
此指令与 C/C++ 指令相同:c_cflag &= ~0xFFFFFF02
,但您要执行的操作是:c_cflag &= ~2
.
要仅清除位 1,您有两种可能性:
And byte [c_lflag], 0xFD
; OR:
And dword [c_lflag], 0xFFFFFFFD