ATmega128:16位数字的加法和减法(汇编)
我正在使用 ATmega128 微控制器,据说需要添加两个 16 位数字。我正在使用 AVR Studio,这就是我到目前为止所得到的:
.include "m128def.inc";
.equ ramstart = 0x100
.def temp = r16
.dseg
.org ramstart
number1: .byte 2
number2: .byte 2
.cseg
.org 0
rjmp start
start:
; number1 := 0x7856
ldi temp, low(number1)
sts number1, temp
ldi temp, high(number1)
sts number1+1, temp
; number2 := 0x34B2
lds temp, number1
sts number2, temp
lds temp, number1+1
sts number2+1, temp
slutt:
rjmp slutt
这离我第一次使用任何类型的程序集已经不远了,我知道我做错了什么,但似乎不知道是什么。我错过了进位标志吗?
I'm working with a ATmega128 microcontroller and supposedly need to add two 16-bit numbers. I'm using AVR Studio and this is what I got so far:
.include "m128def.inc";
.equ ramstart = 0x100
.def temp = r16
.dseg
.org ramstart
number1: .byte 2
number2: .byte 2
.cseg
.org 0
rjmp start
start:
; number1 := 0x7856
ldi temp, low(number1)
sts number1, temp
ldi temp, high(number1)
sts number1+1, temp
; number2 := 0x34B2
lds temp, number1
sts number2, temp
lds temp, number1+1
sts number2+1, temp
slutt:
rjmp slutt
This is not far from the first time I'm using any type of assembly, I know I'm doing something wrong, but can't seem to figure out what. Am I missing the carry flag?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
带着铅笔和纸回到小学。如果我想加1234和5678
4+8是2进位1
等等,
个位上方的进位位很重要,称为进位输入,进位
离开最左列的位被执行。
如果我的纸张宽度只能一次添加两列怎么办?
我从较低的两组数字开始,需要一个零作为进位输入。我得到的结果是 12 和进位输出。
现在我将该进位取出,将其用作接下来两位数字的进位。这个加法器我必须能够从先前的添加中取出进位并将其用作此添加的进位。
当一切都说完了,我得到 69 和 12,把它们加在一起我得到 6912,但不需要一个完整的 4 位加法器来到达那里。您可以永远重复此操作,或者直到耗尽内存、寄存器或时钟周期。
avr 可能有其他方法来解决问题,但大多数处理器至少有两种形式的加法和两种形式的减法,以便您可以将加法器级联到您需要的宽度。检查一下 avr 的指令集,你就会明白上面发生的事情。
编辑:
AC示例可能会有所帮助...(切换到十六进制)
编辑2:
我希望这不是家庭作业...
结果是r20高字节,r21低字节
如果你需要从ram读取有很多方法,假设 16 位数字是小端序
r0 结果的下半部分,r1 上半部分。
或使用 x、y 或 z 指针寄存器之一
Back to gradeschool with pencil and paper. If I want to add 1234 and 5678
4+8 is 2 carry the 1
and so on
the carry bit above the ones column is significant, it is called the carry in, and the carry
bit that leaves the leftmost column is carry out.
What if I only had paper wide enough to add two columns at a time?
I start with the two lower sets of digits, and I require a zero as a carry in. I get a result 12 with a carry out.
Now I take that carry out, use it as a carry in for the next two digits. This adder I must be able to take a carry out from a prior add and use it as the carry in for this add.
When all is said and done I get 69 and 12, put those together I get 6912 but didnt need a full 4 digit adder to get there. You can repeat this forever or until you run out of memory, registers or clock cycles.
The avr may have other ways to solve the problem, but most processors at least have two forms of add and two forms of subtract so that you can cascade the adder to be as wide as you need. Examine the instruction set for the avr and what is going on above should jump out at you.
EDIT:
A C example might help...(switching to hex)
EDIT2:
I hope this is not a homework assignment...
result is in r20 high byte, and r21 low byte
if you need to read from ram there are many ways, this assumes the 16 bit numbers are little endian
r0 low half of result, r1 upper half.
or use one of the x,y,or z pointer registers
好吧,你并没有真正发出任何附加指令。我无论如何都不是 AVR 程序员,但快速浏览了一下 ATmega128 的指令集后,这样的事情似乎更正确。我假设您的汇编器使用 Intel 语法,并且数字存储为 Little Endian。
因此,结果存储在
r17:r16
中,例如,高字节存储在r17
中,低字节存储在r16
中。Well, you're not really issuing any addition instruction. I'm not an AVR programmer in any way, but after a quick glance at the instruction set of the ATmega128, something like this seems much more correct. I'm assuming your assembler uses the Intel syntax and that the numbers are stored as Little Endian.
The result is therefore stored in
r17:r16
, e.g. the high byte inr17
, and the low byte inr16
.您的数据表具有来自此<的
add
和adc
/a> 链接。正如我上面猜测的,也许您需要使用程序内存加载、ldm 来获取您的数字。基本上:
上面的代码不起作用,并且有一个工作示例...
如果我使用后递增 ldm 命令正确理解上下文并且所有寄存器都是 8 位。
Your datasheet has
add
andadc
from this link. As I guessed above, perhaps you need to use program memory loads, ldm to get at your numbers.Basically:
Above code won't work and there is a working example...
If I'm understanding the context correctly with the post-increment ldm command and all registers are 8-bit.
符号“number1”具有地址的值,而不是该地址的内容。
由于您已将“number1”放置在 .ORG RAMSTART 中,这可能是 0100 Hex,那么
low(number1) 等于 00,high(number1) 等于 01
如果你想要地址“number1”的内容,你必须首先将该地址放入一个
16 位地址寄存器,例如 Z 寄存器 = (R30,R31) 由以下
LDI R30, HIGH(number1)
LDI R31, LOW(number1)
现在 Z 寄存器可用于通过以下方式寻址地址“number1”中的 VALUE:
LD R16,Z+
LD R17.Z
现在 R16,R17 中有 16 位值
现在您必须对“number2”
LDI R30,HIGH(number2) 执行相同的操作
LDI R31,低(编号2)
LD R18,Z+
LD R19.Z
现在你在 R18、R19 中得到了第二个 16 位数字
现在你将它们与从 LSB 到 MSB 的进位相加
ADD R19,R17 ;添加 LSB 的第一个
ADC R18,R16 ;然后将 MSB 与进位位相加
答案现在在 R18,R19
结论:AVR 有一个非常粗鲁、低效的指令集。然而,它比 8051 有一个优势:也就是说,堆栈可以位于 RAM 中的任何位置,这允许您运行多个进程,每个进程都有自己的堆栈。
但总的来说,与冯·诺依曼架构相比,所有哈佛架构处理器都很糟糕。
如果上帝保佑,我希望有人能制作一个基于 8085 或 Z80 的微控制器,带有片上 RAM 和闪存,让所有引脚都可以用作 I/O 端口!
The symbol "number1" has the value of an address, not the contents of that address.
Since you have placed "number1" at .ORG RAMSTART, which is probably 0100 Hex, then
low(number1) is equal to 00 and high(number1) is equal to 01
If you want the CONTENTS of the address "number1", you have to first get the address into a
16-bit address register, for example the Z register = (R30,R31) by the following
LDI R30, HIGH(number1)
LDI R31, LOW(number1)
Now the Z register can be used to address the VALUE in the address "number1" by:
LD R16,Z+
LD R17.Z
Now you have the 16 bit value in R16,R17
Now you have to do the same for "number2"
LDI R30, HIGH(number2)
LDI R31, LOW(number2)
LD R18,Z+
LD R19.Z
Now you have the second 16-bit number in R18, R19
Now you add them together with carry from the LSB to the MSB
ADD R19,R17 ;add the LSB's first
ADC R18,R16 ;then add the MSBs with the carry bit
The answer is now in R18,R19
Conclusion: The AVR has a really crass, inefficient instruction set. It has one advantage over the 8051, however: That is, the stack can be anywhere in RAM, which allows you to have multiple processes running, each with their own stacks.
But in general, all Harvard architecture processors SUCK compared to von Neumann architectures.
If only, please God I wish, somebody made a microcontroller based on the 8085 or Z80, with on-chip RAM and FLASH, leaving all the pins free to be I/O ports!