DevCN
菜单
全部文章快讯开发深度热点

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。若业务要求非法输入报告失败,应设计额外返回状态,而不是静默钳制。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。