如何在GCC汇编中使用call getchar@PLT逐个读取字符串字符并验证输入
问题需求
需要将以下C代码转换为x86汇编,要求使用getchar@PLT逐个读取输入字符,完成循环输入与验证逻辑:
puts("Enter a string of 0s and 1s: "); while ( ((input = getchar()) != '\n') ) { if ( (input != '0') && (input != '1') ) { // invalid input puts("ERROR: invalid input"); return 1; } }
用户已完成部分汇编代码(仅实现提示打印与简单读取),现需补充循环逻辑、getchar@PLT调用及输入验证功能:
.section .data input_prompt: .asciz "Enter a string of 0s and 1s: " invalid_message: .asciz "Invalid input: program terminating\n" newline: .byte 10 state: .int 0 # initial state (EE) .section .bss input: .byte 0 .section .text globl main main: # Print the input prompt movl $4, %eax # syscall: write movl $1, %ebx # file descriptor: stdout lea input_prompt, %ecx # pointer to the message movl $29, %edx # message length int $0x80 # invoke syscall # Read user input movl $3, %eax # syscall: read movl $0, %ebx # file descriptor: stdin lea input, %ecx # buffer to store input movl $4, %edx # buffer size int $0x80 # invoke syscall
实现方法
1. 替换系统调用为getchar@PLT调用
getchar()从标准输入读取单个字符,32位x86调用约定下返回值存在%eax寄存器(字符内容在低8位%al中),直接调用即可逐个获取输入,无需保留原read系统调用。
2. 实现循环逻辑
循环核心流程:调用getchar → 判断是否为换行符 → 是则退出循环,否则验证字符有效性:
- 用
jmp直接进入循环入口; - 调用
getchar@PLT后,将%al与换行符(0xA)比较,通过je(相等则跳转)指令退出循环。
3. 输入验证逻辑
获取字符后,依次判断是否为'0'(ASCII码0x30)或'1'(ASCII码0x31):
- 匹配
'0'或'1'则回到循环开头,继续读取下一个字符; - 若都不匹配,打印错误信息并返回1终止程序。
4. 完整汇编代码
.section .data input_prompt: .asciz "Enter a string of 0s and 1s: " invalid_message: .asciz "ERROR: invalid input\n" .section .text globl main main: # 打印输入提示 movl $4, %eax movl $1, %ebx lea input_prompt, %ecx movl $29, %edx int $0x80 loop_start: # 调用getchar读取单个字符,返回值存在%eax(低8位%al为字符) call getchar@PLT # 判断是否为换行符,是则退出循环 cmpb $0xA, %al je loop_exit # 验证是否为'0',是则继续循环 cmpb $0x30, %al je loop_start # 验证是否为'1',是则继续循环 cmpb $0x31, %al je loop_start # 输入无效:打印错误信息 movl $4, %eax movl $1, %ebx lea invalid_message, %ecx movl $20, %edx # 错误信息长度 int $0x80 # 返回1表示程序异常终止 movl $1, %eax movl $1, %ebx int $0x80 loop_exit: # 正常退出程序,返回0 movl $1, %eax movl $0, %ebx int $0x80
关键细节说明
getchar@PLT是动态链接libc的过程链接表条目,无需手动处理函数地址;- 字符比较用
cmpb(字节比较),因为单个字符占1字节; - 原代码中未用到的
.bss段、state、newline变量可直接移除,简化代码结构; - 退出程序使用
exit系统调用(%eax=1),返回值通过%ebx传递。
内容的提问来源于stack exchange,提问作者Erique
相关产品推荐
相关产品推荐

