汇编中寄存器与十六进制值比较失效及简化实现咨询
问题分析与解决方案
兄弟,你踩了一个典型的键值编码不匹配的坑!
你提到已经把按键“2”对应的0x00000002存入r1,但你的比较逻辑用的是0x30-0x39——这是ASCII字符'0'-'9'的十六进制值,和你存在r1里的原始按键硬件值完全不是一回事,自然不会触发跳转啦!
第一步:修正比较逻辑
有两种思路可以解决这个匹配问题:
思路1:直接用原始键值做比较
既然r1里存的是按键对应的硬件键值(比如数字“1”对应0x1,“2”对应0x2...“9”对应0x9,“0”可能对应0xA或0x0,取决于你的输入驱动逻辑),那把比较的立即数改成对应的原始值就行:
cmp r1, #0x01 ; 匹配按键"1" beq savekey cmp r1, #0x02 ; 匹配按键"2" beq savekey cmp r1, #0x03 ; 匹配按键"3" beq savekey ; ... 依次类推到按键"9"和"0" cmp r1, #0x09 ; 匹配按键"9" beq savekey cmp r1, #0x00 ; 如果"0"键对应原始值0x0的话 beq savekey
思路2:先将原始键值转为ASCII码再比较
如果你的业务逻辑最终需要处理ASCII码,不如先把r1里的原始键值转换成对应的ASCII码,再用你原来的比较逻辑:
; 假设数字键"1"对应原始值0x1,"0"对应0x0 add r1, r1, #0x30 ; 原始值+0x30 = 对应ASCII码(比如0x1+0x30=0x31='1') ; 接下来用你原来的比较逻辑就行 cmp r1, #0x30 beq savekey cmp r1, #0x31 beq savekey ; ... 直到#0x39
第二步:用更简洁的写法替代逐个判断
逐个cmp+beq太啰嗦了,利用数字键值的连续性,我们可以用范围判断来简化代码:
方案1:范围边界判断(通用写法)
如果原始键值是连续的(比如0x0-0x9对应数字0-9),直接判断是否在这个区间内:
cmp r1, #0x0 blt skip_save ; 小于0,不是数字键,跳过 cmp r1, #0x9 bgt skip_save ; 大于9,不是数字键,跳过 b savekey ; 走到这里说明是数字键,直接跳转 skip_save: ; 非数字按键的处理逻辑
如果是ASCII码的范围(0x30-0x39),逻辑完全一样,只是把比较的立即数换成0x30和0x39即可。
方案2:位运算快速判断(ARM架构优化)
对于ARM架构,还可以用位运算快速判断是否是0-9的数值(假设r1的高24位都是0):
; 针对原始键值0x0-0x9的情况 ands r2, r1, #0xF0 ; 0-9的二进制高4位都是0,与0xF0结果为0 beq savekey ; 结果为0则跳转 ; 针对ASCII码0x30-0x39的情况 sub r2, r1, #0x30 ; 先把ASCII码转成0-9的数值 ands r2, r2, #0xF0 beq savekey
这种写法比两次cmp更高效,适合对性能有要求的场景。
内容的提问来源于stack exchange,提问作者Exchange_programming
相关产品推荐
相关产品推荐

