assembly - 处理 68000 汇编语言中的错误的最佳方法是什么?
问题描述
我最近一直在写很多 68K 的汇编语言,我注意到一个模式,大致如下:
do_something:
movem.l d2-d5/a2-a3,-(sp)
...
jsr xxx
tst.l d0
beq open_error
...
jsr yyy
tst.l d0
bmi read_error
...
move.l #ERR_OKAY,d0
bra exit
open_error:
move.l #ERR_OPEN,d0
bra exit
read_error:
move.l #ERR_READ,d0
exit:
movem.l (sp)+,d2-d5/a2-a3
rts
也就是说,我有很多分支到只设置返回码然后分支到一些清理指令的指令。
有没有一些聪明的方法可以更有效地做到这一点,或者我只是在做需要做的事情?
我能想到的唯一优化是在最常见(无错误)路径上保存一个分支:
...
move.l #ERR_OKAY,d0
exit:
movem.l (sp)+,d2-d5/a2-a3
rts
open_error:
move.l #ERR_OPEN,d0
bra exit
read_error:
move.l #ERR_READ,d0
bra exit
解决方案
如果您必须(或选择)遵守您当前使用的 ABI(在 中返回错误代码d0
,并保留寄存器d2-d7/a2-a6
),那么您无能为力。
在某些特殊情况下,您可能会对某些操作进行微优化,例如,如果ERR_OPEN
碰巧-1
(并且您可以处理修改后的d0
),您可以替换:
tst.l d0
beq open_error
...
open_error:
move.l #ERR_OPEN,d0
bra exit
经过:
subq.l #1,d0
bcs exit ; carry is only set if `d0` was 0 before
如果你想优化速度而不是代码大小,你可以替换所有
bra exit
由相应的
movem.l (sp)+,d2-d5/a2-a3
rts
如果你在接口上有更多的自由,你可以说“我的函数可能会破坏寄存器d0-d5/a0-a3
并让调用者处理它(所有这些bra exit
都会变成一个rts
)。
此外,特别是如果您的函数仅从单个其他函数调用,该函数本身d0
在调用它后直接检查,您可以简单地“内联”您的函数并直接分支到实际处理每个错误的代码(但对于更大的函数,这可能会以更差的可读性为代价做出微不足道的改进)。
如果您主要关心的是冗长,我真的建议将其移植到更高级别的语言(并且仅手动优化性能关键功能 - 如果您实际上可以比您的编译器更好地实现它们)。
推荐阅读
- python - 检查 timedelta 是否大于值(Python)
- flutter - 在 Flutter 中调试 web-socket 问题
- javascript - jQuery函数没有运行
- python - tf.while_loop 与 tf.concat 的奇怪行为
- html - 阻止 div 继承引导 div 的宽度
- azure-devops-server-2019 - Azure Devops Server 2019 中的多阶段 YAML 发布管道
- python - 在 Veracrypt 驱动器中配置 VSCode Python 解释器
- javascript - json用嵌套响应reactjs解析isse
- javascript - 如何删除这些全局变量并在它们发生时显示增量?
- string - 我的字符串已初始化,但仍显示为 null (flutter - dart)