如何在amd64 GAS汇编中读取键盘输入字符并显示到屏幕
amd64平台GAS汇编实现键盘输入读取与屏幕显示
先解决你卡壳的ioctl cmd参数问题:amd64 Linux下和termios相关的常用ioctl命令值可以直接使用,不需要依赖头文件定义:
TCGETS:值为0x5401,传入指向termios结构体的缓冲区指针,内核会把当前终端的配置写入该缓冲区TCSETS:值为0x5402,传入修改后的termios结构体指针,内核会立刻更新终端配置- 终端默认开启规范输入模式(canonical mode):输入内容会存在行缓冲区里,只有按下回车后程序才能通过read读到内容,同时默认开启输入回显,你敲的字符会自动显示在屏幕上。你给出的预期运行效果用默认模式就能实现,不需要修改终端配置。
最简可运行实现(匹配预期效果)
直接调用Linux原生read/write系统调用即可,不需要操作ioctl,完整代码如下:
.section .data prompt: .ascii "please input some character: " prompt_len = . - prompt buf: .space 128 # 预留128字节存储输入内容 .section .text .global _start _start: # 打印输入提示 movq $1, %rax # sys_write系统调用号 movq $1, %rdi # 参数1:文件描述符stdout=1 movq $prompt, %rsi # 参数2:提示字符串首地址 movq $prompt_len, %rdx # 参数3:字符串长度 syscall # 读取键盘输入 movq $0, %rax # sys_read系统调用号 movq $0, %rdi # 参数1:文件描述符stdin=0 movq $buf, %rsi # 参数2:缓冲区首地址 movq $128, %rdx # 参数3:最大读取长度 syscall # read执行完成后,rax存储实际读到的字节数(包含末尾输入的回车符) # 将读到的内容输出到屏幕 movq %rax, %rdx # 写入长度取read返回的实际读取长度 movq $1, %rax movq $1, %rdi movq $buf, %rsi syscall # 退出程序 movq $60, %rax # sys_exit系统调用号 movq $0, %rdi # 退出码0 syscall
编译运行命令:
as -o program.o program.s ld -o program program.o chmod +x program ./program
运行后会直接匹配你给出的效果:打印提示字符串,输入内容按回车后,程序会原样输出你输入的内容。
扩展:逐字符即时读取实现
如果需要实现敲键即读、不需要按回车的效果,才需要用ioctl修改termios配置,核心是关闭c_lflag字段里的ICANON(规范模式)和ECHO(自动回显)位。amd64平台下termios结构体关键偏移:
- c_lflag字段偏移12字节,占4字节
- c_cc配置数组中,VMIN(最小读取字符数)偏移17字节,VTIME(读取超时)偏移16字节
核心配置代码片段:
# 预留36字节空间存储termios结构,仅修改需要的配置位即可 termios_buf: .space 36 # 读取终端原有配置 movq $16, %rax # sys_ioctl系统调用号 movq $0, %rdi # stdin文件描述符 movq $0x5401, %rsi # TCGETS命令 movq $termios_buf, %rdx syscall # 修改配置:关闭ICANON(值0x2)、ECHO(值0x8)位 andb $0xF5, termios_buf+12 # c_lflag偏移12字节,清对应标志位 movb $0, termios_buf+16 # VTIME设为0,不设读取超时 movb $1, termios_buf+17 # VMIN设为1,读到1个字符就返回 # 写回修改后的配置 movq $16, %rax movq $0, %rdi movq $0x5402, %rsi # TCSETS命令 movq $termios_buf, %rdx syscall # 后续read调用会逐字符返回,不需要等回车,且输入不会自动回显,需自行调用write输出读到的字符
注意如果修改了终端配置,程序退出前需要把原有配置恢复,否则终端会出现输入不显示、换行异常的问题。
内容的提问来源于stack exchange,提问作者OnlyWick
相关产品推荐
相关产品推荐

