ARM64中LSR指令为何不影响C标志?奇偶判断程序异常排查
ARM64汇编判断奇偶时C标志未更新的问题
问题代码
//********************************** // Check if number is even or not * //********************************** .global _start _start: MOV X5, #13 // Load the number // Set up everything for print mov X0, #1 // 1 = StdOut mov X8, #64 // Linux write system call // If number is divisible by two, C flag is clear LSR X6, X5, #1 // Divide by 2 B.CS odd // If NOT divisible by 2, jump to odd even: ldr X1, =evenD // Load addr of even str mov X2, #11 // Set up length of even str B end // B to avoid odd case odd: ldr X1, =oddD // Load addr of odd string mov X2, #12 // Set up length of odd str end: svc 0 // Tell Linux to print mov X0, #0 // Ret code 0 mov X8, #93 // Code 93 to terminate svc 0 // Tell linux to terminate // Data section .data evenD: .ascii "It's even!\n" oddD: .ascii "That's odd!\n"
遇到的问题
- 执行
LSR X6, X5, #1后C标志无变化,导致B.CS始终不触发跳转,所有数字都被判定为偶数。 - 尝试使用
LSRS指令时汇编报错:Error: unknown mnemonic 'lsrs' -- 'lsrs X6,X5,#1'
原因分析
ARM64指令集和ARM32存在关键差异:
- ARM32中可通过给移位指令添加
S后缀(如LSRS)更新标志位,但ARM64没有单独的带S后缀的移位指令。 - 普通的
LSR指令仅完成移位运算,不会修改CPSR寄存器中的任何标志位,因此你的代码中C标志始终保持初始状态,无法触发跳转。
解决方案
方案一:用MOVS配合移位更新标志位
将原代码中的LSR X6, X5, #1替换为:
MOVS X6, X5, LSR #1
MOVS指令会执行移位操作,同时将移出的最低位(原数字的奇偶判断位)设置到C标志中。若原数字为奇数,最低位是1,移位后C标志会被置位,B.CS就能正确跳转到odd分支。
方案二:用TST指令直接检测最低位(更简洁)
判断奇偶最直接的方式是检测数字的最低位,使用TST指令与#1相与,通过Z标志判断结果:
TST X5, #1 // 与#1相与,结果为0则Z标志置位(偶数),否则Z标志清零(奇数) B.NE odd // Z标志未置位时跳转至odd分支(数字为奇数)
这种方式无需移位,逻辑更直观,也避免了标志位更新的问题。
内容的提问来源于stack exchange,提问作者Stargarth
相关产品推荐
相关产品推荐

