如何在Ubuntu环境的x64 Intel汇编中实现字符判断的if-else语句
问题分析与修正方案
核心错误点
- 你当前的比较逻辑是在对比内存地址而非字符的实际值:
cmp rsp, r9是把存储输入字符的栈地址,和.catletter的内存地址做对比,这两个地址不可能相等,自然不会触发跳转。 - 尝试
cmp rsp, "c"或cmp rsp, 67时,错误地把栈指针(地址)当成了存储的字符值;且67是大写字母C的ASCII码,你需要的小写c对应ASCII码是99。
正确实现方式
要对比的是输入的字符值,而非它的存储地址。可以直接读取栈中存储的字节,和目标字符常量做对比,以下是修正后的完整代码:
.global _start .intel_syntax noprefix _start: // Print Question mov rax, 1 mov rdi, 1 lea rsi, [.the_ask] mov rdx, 28 syscall // Load Input into memory mov rax, 0 sub rsp, 8 // 分配8字节栈空间存输入 mov rdi, 0 lea rsi, [rsp] mov rdx, 1 syscall // Print Newline mov rax, 1 mov rdi, 1 lea rsi, [.newline] mov rdx, 2 syscall // 正确的字符比较逻辑 cmp byte [rsp], 'c' // 直接对比栈中存储的字节与字符'c' je _docatstuff cmp byte [rsp], 'd' // 对比栈中字节与字符'd' je _dodogstuff // Exit (输入不匹配时执行) mov rax, 60 mov rdi, 1 syscall _docatstuff: // meow at user mov rax, 1 mov rdi, 1 lea rsi, [.catstuff] mov rdx, 4 syscall // newline mov rax, 1 // 显式设置syscall编号,避免依赖之前的寄存器值 mov rdi, 1 lea rsi, [.newline] mov rdx, 2 syscall // exit mov rax, 60 mov rdi, 0 syscall _dodogstuff: // bark at user mov rax, 1 mov rdi, 1 lea rsi, [.dogstuff] mov rdx, 4 syscall // newline mov rax, 1 mov rdi, 1 lea rsi, [.newline] mov rdx, 2 syscall // exit mov rax, 60 mov rdi, 0 syscall .the_ask: .asciz "Please Enter: (c)at, (d)og: " .newline: .asciz "\n" .catstuff: .asciz "meow" .dogstuff: .asciz "woof"
关键修正说明
- 字符对比逻辑:用
cmp byte [rsp], 'c'直接读取栈中存储的1字节输入字符,和字符常量'c'(汇编器会自动转换为对应的ASCII码99)做对比,这才是正确的字符值比较。 - 冗余代码移除:删掉了
.catletter和.dogletter两个不必要的字符常量,直接用字符常量对比更简洁。 - syscall寄存器规范:在打印换行时显式重新设置
rax和rdi,避免依赖之前的寄存器状态,让代码更健壮。
内容的提问来源于stack exchange,提问作者synnøve
相关产品推荐
相关产品推荐

