Atmel studio assembly:8位数字的平方根

Atmel studio assembly : Square root of an 8-bit number

我在 Atmel Studio 中使用 ATmega328P,我必须制作一个 function/algorithm,它采用 8 位数字并计算它的平方根。结果必须在两个寄存器中给出,一个用于整数部分,另一个用于小数部分。

我在想这个:根必须介于给定的数字和 0(或 1)之间。所以我会 lsr(除以 2),它会检查它是大于、小于还是等于,然后以更精确的方式重试,这样它就会变得越来越精确。

问题是整数不正确而且我不知道如何将它写入代码,因为我是汇编新手。我也可以 post 我目前所做的。

感谢您的任何建议和帮助。

只是为了完整性(或无用的展示),这里是如何通过线性搜索(在大多数情况下对于 0-15 值仍然更快,这应该是在大多数情况下更快,比使用乘法的二进制搜索)。

root = -1
square = 0
addValue = 1
while (square <= input) {
    square += addValue
    addValue += 2
    ++root
}
; here root == trunc(sqrt(input))

所以,如果你不需要小数部分,这就足够了,或者如果你被允许使用至少 256B 长的 LUT 用于小数部分,连同这个。

用 8 位整数寄存器编写正确的十进制 sqrt 实际上是一项相当大的工作,我不会剥夺您的所有乐趣。 :P ..

检查各种算法,不要忘记有限范围的小数可以通过乘以某个 "base_exp" 值变成整数。

即从 0.00 到 15.99 的值可以通过执行 *100 (0-1599) 变成 11 位整数,并且 (100*100) 的 sqrt 是 100,所以通过输入 *10000 你将得到值 0-2550000(至少需要22 位,四舍五入为 24b),然后对其求整数平方根,结果为 *100(适合 11 位),因此您可以通过除以 100 将其进一步拆分为两个值。

这对于人类来说可能看起来很简单,但在现实世界中,当使用 8/16b 寄存器进行十进制计算时,通常是根据这个原理来完成的,而是使用 2 的幂,即 *256*256,这可以是只需将值左移 16 位即可完成。除以 256 会将值向右移动 8。

因此,对于使用二进制数的每位数字方法,您将需要创建 24 位 addition/subtraction/shifter 代码段。那么输入的数字就是24位数字的最高8位。 (即输入值 10 => (10<<16) == 0x0A0000)=> 简单移位。计算它的 sqrt(0x0329 或 0x032A,取决于你是否设法在最后一位截断或四舍五入),就是这样,结果肯定适合 12 位,高 4 是整个部分 0-15,低 8 位是 "amount of 1/256" 值中的小数 (0x29/256 = 0.16015625)。可以通过简单的 shifting/anding 再次拆分,即不需要 mul/div 操作。

所以仍然需要做很多工作,但这是合理的(在 8b CPU 上做 24 位 multiplication/division 比做 add/sub/shifting 扩展要痛苦得多)。并解释为什么您选择结果的 4:8 fixed-point 格式,以使用结果小数部分的完整 8 位精度,并使进一步的二进制计算更简单。 (在 8:8 固定点 0.5 = 0x0080 ... 尝试添加它,看看会发生什么:0x0080 + 0x0080 = 0x0100 = 1.0 没有对结果进行任何复杂的篡改......这就是我们如何对 8 进行低精度小数计算位 CPUs,例如对于 sin/cos 效果,multiplication/division 也更简单,同样对于 0.5:0x0080 * 0x0080 = (0x4000>>8) = 0x0040 = 0.25).