汇编语言输入字符与ASCII值比较未触发预期跳转问题求助
问题排查与修正方案
核心Bug:概念混淆导致比较对象完全错配
你误以为sys_read执行完之后,ecx寄存器里存的是用户输入的'f'字符,实际上这是完全错误的认知:
- 你调用
sys_read的时候,mov ecx, conv是把conv缓冲区的内存首地址作为入参传给内核,告诉内核“你读到的输入字符就写到这个地址指向的内存里”。 sys_read执行完之后,ecx寄存器的值不会被内核修改,还是之前存的缓冲区首地址(类似0x8049230这种数值),根本不是输入字符的ASCII值。输入的'f'是存在这个地址指向的内存空间里,不是在ecx寄存器里。- 这时候你写
cmp ecx, 66h,相当于拿内存地址和'f'的ASCII值(0x66)做对比,两个数值完全不在一个量级,条件永远不会成立,je跳转自然触发不了。
正确的比较写法
你需要对比的是conv地址指向内存里存的第一个输入字符的值,而非ecx寄存器里的地址,两种常见修正写法:
- 直接寻址对比:
; 直接比较conv地址下存储的第一个字节 cmp byte [conv], 'f' je toFarenheit cmp byte [conv], 'c' je toCelcius - 先把字符加载到通用寄存器再对比,可读性更高:
注:直接写mov al, [conv] cmp al, 'f' je toFarenheit cmp al, 'c' je toCelcius'f'、'c'这种字符字面量,比硬写ASCII hex值的可读性好很多,也不容易写错。
其他附带的问题点
- 你代码里的
int 80h缺少0x前缀,标准32位Linux汇编的软中断写法是int 0x80,部分汇编器虽然能兼容,但属于不规范写法,换环境就可能报错。 - 你给
sys_read设置的读取长度是4字节,用户输入f/c之后按回车,内核会实际往缓冲区写入两个字节:第一个是你输入的f/c,第二个是回车对应的换行符(ASCII 0x0A),如果后续要做多步输入处理,记得要过滤这个换行符。
修正后的关键逻辑参考
; 原有输入读取逻辑保留 mov eax, 3 mov ebx, 0 mov ecx, conv mov edx, 4 int 0x80 ; 原有回显输入的逻辑保留 mov eax, 4 mov ebx, 1 mov ecx, conv mov edx, 4 int 0x80 ; 修正后的对比逻辑 mov al, [conv] cmp al, 'f' je toFarenheit ; 匹配输入c的情况 cmp al, 'c' je toCelcius toCelcius: ; 原有C分支逻辑保留 mov edx, lenTestC mov ecx, testMsgC mov ebx, 1 mov eax, 4 int 0x80 jmp exit toFarenheit: ; 原有F分支逻辑保留 mov edx, lenTestF mov ecx, testMsgF mov ebx, 1 mov eax, 4 int 0x80 exit: mov eax, 1 int 0x80
内容的提问来源于stack exchange,提问作者user14639030
相关产品推荐
相关产品推荐

