Atmel studio 汇编:8 位数字的平方根
Posted
技术标签:
【中文标题】Atmel studio 汇编:8 位数字的平方根【英文标题】:Atmel studio assembly : Square root of an 8-bit number 【发布时间】:2017-05-19 16:06:05 【问题描述】:我在 Atmel Studio 中使用 ATmega328P,我必须创建一个函数/算法,它需要一个 8 位数字并计算它的平方根。结果必须在两个寄存器中给出,一个用于整数部分,另一个用于小数部分。
我在想这个:根必须在给定的数字和 0(或 1)之间。所以我会 lsr(除以 2),它会检查它是否更大、更小或相等,然后以更高的精度重试,这样它会变得越来越精确。
问题是整数不正确,而且我不知道如何将其放入代码中,因为我是汇编新手。我也可以发布我目前所做的。
感谢您的任何建议和帮助。
【问题讨论】:
256 字节长的查找表如何? (嗯,更像是 512B 长,因为小数部分......它是定点数学 8:8 吗?我猜)(如果你只有 256B 的小数,整个部分可以通过一个循环简单+缓慢地完成) 遗憾的是,它是和分配,我必须计算它,否则这将是一个可行的选择,但感谢您的输入。 虽然我会在万不得已的情况下这样做,如果我没有弄清楚的话。 (您建议编写一个程序,将插入的数字与 256 个结果进行比较,如果正确则结束?) 这取决于您需要多少复杂性和精度。因为您可以从 0 到 15 进行蛮力以覆盖 8 位无符号数的整个范围。它可以通过二分搜索进一步优化 ARGH...这不是 8:8 定点,这有点...在现实世界中不可用,但适合分配。在 8:8 定点中,第二个 8 位(第二个寄存器)的数量为 1/256,即 0 = 0.00, 0x80 = 0.5, 0x29 = 0.16015625, 0xFF = 0.99609375 ... 可直接用于进一步的数学计算。您的 0x17 = 23 更适合输出,但由于它的数量为 1/100,因此会浪费位(精度较低),并且难以重用于进一步的二进制数学计算。您应该指定有问题的值是如何拆分到寄存器中的。 【参考方案1】:只是为了完整性(或无用的展示),这里是如何通过线性搜索仅用整数完成任务,而不用乘法(在大多数情况下,对于 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 位加法/减法/移位代码段。然后输入数字是 24 位数字的最高 8 位。 (即输入值10
=> (10<<16) == 0x0A0000
)=> 简单移位。计算它的 sqrt(0x0329 或 0x032A,取决于你是否设法在最后一位进行截断或舍入),就是这样,结果肯定适合 12 位,高 4 位是整个部分 0-15,低 8 位是“1/256 的数量”值(0x29/256 = 0.16015625)的小数。可以通过简单的移位/与再次拆分,即不需要 mul/div 操作。
所以它仍然需要做很多工作,但这是合理的(在 8b CPU 上进行 24 位乘法/除法比进行加法/减法/移位扩展要痛苦得多)。并解释为什么您选择 4:8 fixed-point 格式的结果,以使用来自结果的小数部分的完整 8 位精度,并使其更简单地进行进一步的二进制计算。 (在 8:8 定点 0.5 = 0x0080 ...尝试添加它,看看会发生什么:0x0080 + 0x0080 = 0x0100 = 1.0 没有任何复杂的结果篡改......这就是我们在 8 位 CPU 上进行低精度十进制计算的方式,例如对于 sin/cos 效果,乘法/除法也更简单,同样对于 0.5:0x0080 * 0x0080 = (0x4000>>8) = 0x0040 = 0.25)。
【讨论】:
以上是关于Atmel studio 汇编:8 位数字的平方根的主要内容,如果未能解决你的问题,请参考以下文章
Proteus VSM Studio汇编 + 8位数码管+按键扫描