ARM64 条件选择:将分钟数限制在有效范围
通过 cmp 与 csel 实现有符号范围钳制,将负数置零、超限值置为 1440,理解条件标志和选择指令的配合。
本节目标
通过 cmp 与 csel 实现有符号范围钳制,将负数置零、超限值置为 1440,理解条件标志和选择指令的配合。
环境与运行方法
本组限定 Apple Silicon 的 macOS ARM64 与 Clang。保存汇编为 lesson.s,再把下方 C 驱动保存为 main.c,执行 clang -Wall -Wextra -Werror main.c lesson.s -o lesson 后运行 ./lesson。其他架构、操作系统和目标文件格式不能直接照搬符号命名。
C 驱动代码:
#include <stdio.h>
extern long cap_minutes(long value);
int main(void) {
printf("%ld\n", cap_minutes(-5));
printf("%ld\n", cap_minutes(30));
printf("%ld\n", cap_minutes(2000));
return 0;
}核心思路
钳制与拒绝非法输入是不同业务策略。本例明确选择钳制:任何小于零的值变成零,大于 1440 的值变成上限。条件选择根据比较标志选一个寄存器值,不需要显式跳转。
完整示例
.text
.globl _cap_minutes
.p2align 2
_cap_minutes:
cmp x0, #0
csel x0, xzr, x0, lt
mov x1, #1440
cmp x0, x1
csel x0, x1, x0, gt
ret预期输出
0
30
1440逐步理解
第一次 cmp 按有符号 lt 条件选择零寄存器或原输入。随后把上限放进 x1,再比较并按 gt 条件选择上限。两次操作后返回值一定在闭区间内。
x1 是可供本函数临时使用的参数寄存器,没有承诺保存调用者先前内容。若比较的是无符号计数,应改用对应条件码,不能只因为指令相似就复用有符号判断。
常见问题与边界
- lt、gt 与无符号条件码含义不同。
- cmp 后的其他改标志指令可能影响条件选择。
- 钳制会改变输入,不能当成严格校验的替代。
动手练习
测试恰好 0、1440,以及 1441。
参考答案
两个边界保持原值,1441 变成 1440。若业务要求非法输入报告失败,应设计额外返回状态,而不是静默钳制。
文章回复
0 条公开回复