我正在尝试修补一个旧的 8 位汇编程序例程(它恰好是 M6800,但这并不是真正特定于机器的)以获取 16 位值并向下舍入到最接近的 0x50(dec 80)倍数。当前代码截断为最接近的32只需做一件事AND 0xE0
到低字节,这当然会将低 5 位清零,并在不触及高字节的情况下获得正确的结果。
这是进行一些屏幕数学运算,因此输入值仅在以下范围内0xE000
to 0xE7CF
。由于 80 显然不是 2 的幂,所以我不能简单地做到这一点,但考虑到这是一个补丁,我试图将指令数量保持在最低限度,理想情况下不添加通用除法或查找表等。
我很困惑,怀疑没有特别聪明的方法来实现这一点。 80 不是 2 的幂,而是 16 的倍数……这对我一点帮助都没有吗?任何见解、指示等都将受到赞赏。谢谢。
首先,自从80 = 16 * 5
, 向下舍入为倍数80
表示向下舍入为两者的倍数16
and 5
。第一个很容易右移,所以现在我们只剩下mod 5
part:
def mod5(x):
return x % 5
def round80(x):
x >>= 4
x -= mod5(x)
x <<= 4
return x
mod5
不是那么容易做到的,但是有一个梅森模的巧妙构造 http://homepage.cs.uiowa.edu/%7Ejones/bcd/mod.shtml#exmod5首先计算mod15
,然后将值降低到模 5。一开始并不是那么直观,但它只涉及加法和移位,这应该很容易实现。这是Python版本:
def mod15(x):
x = (x >> 8) + (x & 0xFF)
x = (x >> 4) + (x & 0xF)
if x >= 15: x -= 15
if x >= 15: x -= 15 # (see note)
return x
def mod5(x):
x = mod15(x)
if x >= 5: x -= 5
if x >= 5: x -= 5
return x
def round80(x):
x >>= 4
x -= mod5(x)
x <<= 4
return x
为了安全起见,我验证了此代码的所有可能值:
for i in range(0x10000):
trivial = i - (i % 80)
assert trivial == round80(i)
补充一点:第二个if
代替mod15
实际上可以省略对于您的输入范围,注释掉没有什么区别。如果你需要整个[0,0xffff]
范围内,则无法将其删除。
我不是 M6800 汇编方面的专家,所以我不会尝试编写最终代码,但它应该相对简单,特别是考虑到唯一的 16 位操作是两次移位和第一次加法mod15
.
没有除法,没有乘法,也没有查找表 - 我希望这足够短,可以满足您的需求!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)