如何从二进制数中获取每个数字的ascii
我得到一个 8 位二进制数,并希望在 LCD 屏幕上将其表示为十进制数。
例如,如果我得到 01000011 作为输入,十进制为 67,我首先必须获取 6 的 8 位 ascii 代码,然后获取 7 的 8 位 ascii 代码,并将它们发送到 LCD。
知道如何在 AVR Assembler 中完成此操作吗?
I am getting an 8 bit binary number and want to represent that as a decimal number on a LCD screen.
So for example if I get 01000011 as input, which is 67 in decimal I first have to get the 8 bit ascii code for 6, then the 8 bit ascii code for 7 and send those to the LCD.
Any idea on how this could be done in AVR Assembler?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是来自 @Sebastian 的算法,它计算除以 10 后的商,正确的范围是
[0, 99]
。转换为
byte
是必要的,因为 C 标准要求将任何中间结果提升为至少 16 位的int
,而这种转换会导致 8 位的低效代码位处理器,如 AVR。GCC 翻译过来就是这个。
您始终可以通过
被除数 - 商 * 10
计算余数。以下是根据@Sebastian 的评论对上述方法如何工作的解释。如果您想要数学上复杂的解释,请阅读评论,但这是我可以通过一些基本数学模糊掌握的内容。
基本上,您可以通过乘以除数的倒数来除以一个数字。
n / 3 = n * 0.33..
。要计算
n / 3
的整数商,您可以使用这些源自1 / 3 = 0.33..
的表达式。使用更大的乘数,您可以获得更高的精度,因此结果将是准确的以获得更大的股息。
与二进制数相同。您可以通过这些表达式计算
n / 5
的整数商,这些表达式源自1 / 5 = 0.001100110011..(2)
的二进制小数点表达式。特定精度所需的乘数大小看起来有点不规则,我仍然没有弄清楚它是如何工作的,但出于我们的目的,我们需要在
中除以一个数字
乘以N
[0, 99]10
,即N / 2 / 5
。N / 2 <= 49
,因此n * (1100(2) + 1) / 2^6
最多可达n <= 63< /代码> 就足够了。
因此,我们可以将
N / 10
转换为N / 2 * 13 >> 6.
。让h = N / 2
。h * 13
溢出 8 位,但由于>> 6
会在乘法后丢弃一些低位,可以提前进行一些移位。由于
h <= 49
,h * 3 + (h >> 2)
适合 8 位,这在我们的 C 代码中表示以前见过。GCC 认为不同的计算方式更好。 GCC 的汇编输出可以用 C 重写,如下所示。
旧答案
如果您正在寻找一种算法来计算 8 位数字除以 10 时的商和余数,在 AVR 汇编器中,这段代码可以解决问题。
但不要问我它是如何工作的。这是我通过对 x86 Clang 的优化输出进行逆向工程编写的 AVR GCC 翻译 C 函数的优化输出。所以我基本上偷了两个编译器的工作。
从这个 C 代码。
x86 Clang 制作了这个。
我将其翻译为 C,
然后将其放入 AVR GCC 中。
看起来AVR是一个非常简单的8位机器,甚至没有变量移位。好吧,它仍然可能比 GCC 内置的软件部门更快地完成这项工作。
This is an algorithm from @Sebastian which computes the quotient after dividing by 10, correctly in the range of
[0, 99]
.The casts to
byte
is necessary because the C standard requires to promote any intermediate result to anint
which is at least 16-bit, and such conversion results to inefficient code for 8-bit processors like AVR.GCC translates to this.
You can always calculate the remainder by
dividend - quotient * 10
.Here is an explanation on how the above method works based on @Sebastian's comments. Read the comments if you'd like a mathematically sophisticated explanation, but this is what I can vaguely grasp with some basic math.
Basically, you can divide a number by multiplying the divisor's inverse.
n / 3 = n * 0.33..
.To calculate the integer quotient of
n / 3
, you can use these expressions, derived from1 / 3 = 0.33..
.With a larger multiplier, you get higher precision, so the result will be accurate for a bigger dividend.
Same with binary numbers. You can calculate the integer quotient of
n / 5
by these expressions, derived from the binary point expression of1 / 5 = 0.001100110011..(2)
.The required size of the multiplier for a certain precision looks kind of irregular, and I still haven't figured out how it works, but for our purpose, we need to divide a number
N
in[0, 99]
by10
, which isN / 2 / 5
.N / 2 <= 49
, son * (1100(2) + 1) / 2^6
which works up ton <= 63
suffices.We can thus transform
N / 10
toN / 2 * 13 >> 6
. Leth = N / 2
.h * 13
overflows in 8 bits, but since>> 6
will discard some of the lower bits after the multiplication, it's okay to do some shifts beforehand.Since
h <= 49
,h * 3 + (h >> 2)
fits in 8 bits, and this is represented in the C code that we've seen before.GCC thinks a different way of calculation is better. The assembly output of GCC can be rewritten in C as follows.
old answer
If you are looking for an algorithm to calculate the quotient and remainder when an 8-bit number is divided by 10, in AVR assembler, this code does the trick.
But don't ask me how it works. It is the optimized output of AVR GCC translating a C function that I wrote by reverse-engineering the optimized output of x86 Clang. So I basically stole the work of two compilers.
From this C code.
x86 Clang produced this.
which I translated to C.
which then I put into AVR GCC.
It seems AVR is a very simple 8-bit machine without even variable shifts. Well, still it will do the job probably faster than GCC's software division built-in.