【问题标题】:Add numbers in AVR assembly在 AVR 程序集中添加数字
【发布时间】:2012-06-04 10:27:53
【问题描述】:

如何在 AVR 汇编中做到这一点?

我在不同的 reg 中有 2 个数字(小端序)。

# Number 1
LDI R16 0x…
LDI R17 0x…
LDI R18 0x…
LDI R19 0x…
# Number 2
LDI R20 0x…
LDI R21 0x…
LDI R22 0x…
LDI R23 0x…

我想将它们加在一起并将结果保存到 R20 - R23。

【问题讨论】:

  • Have you tried Google? 如果您还没有,那么 StackOverflow 还不是提问的正确地方。 (如果标准方法不起作用,您应该指出这一点。)
  • 我试过谷歌 ;-) 但如果添加了很多 regis,请不要携带。 - 应该是这样的吗? ADD R20,R16.... ADC R21,R17.... 等等?
  • 是的,你就是这样做的:)

标签: assembly avr


【解决方案1】:

关于它背后的“数学”:与十进制相同:

当添加两个个位数时,必须考虑两种情况。两者之和是一个新的个位数 (5+4 = 9),或者发生“溢出”并且需要另一个数字 (5+6 = 11)。请注意,对于n 数字长度的任何两个数字(以任何基数,无论是 10、2、256 还是其他数字),两者的总和将总是小于最小数字的两倍n+1 位数长度;让ij 是例如长度为1 的数字(以10 为底),也就是说,两者都在09 之间,包括端点。由于10 是长度最小的n+1 = 2,它们的总和总是小于2 x 10

两个数相加时,可能没有溢出,也可能正好溢出 1。进位位存储上次算术运算的溢出;它是 0 或 1。

因此,当添加两个 4x 8 位的数字时(可以看作 4 个“数字”基数 256),第一次添加不会考虑溢出,因此只有 ADD; ADD 可以看作是对x = x + y + 0 的操作。然而,在第一次添加之后,可能需要考虑溢出,这是通过使用ADDC 完成的; ADDC代表x = x + y + carry的操作,其中carry只能是0或1,如上所述。在添加完所有数字后,最后一次添加可能再次导致溢出,这将反映在之后的进位位中,并且可以评估为可能对数字范围的溢出做出反应,例如:

x = x + y;

if ( carry == 1 ) {
  error "The sum is too big for the datatype of x";
}

【讨论】:

  • 在 C 中,您可以编写 unsigned sum = x + y; unsigned carry = (sum < x);(仅适用于无符号值)。一些编译器将使用 add 指令的执行结果,而不是在编译时实际进行比较。
【解决方案2】:

相当简单的操作。第一个操作使用 add,后续添加使用 add-with-carry

# Number 1
LDI R16 0x…
LDI R17 0x…
LDI R18 0x…
LDI R19 0x…
# Number 2
LDI R20 0x…
LDI R21 0x…
LDI R22 0x…
LDI R23 0x…
# Add LSB of 1 and 2, result will be in R20
ADD R20,R16
# Add remaining bytes using the add-with-carry operation
ADC R21,R17
ADC R22,R18
ADC R23,R19 # MSB

结果将覆盖 R20:R23 中的值。

我知道您只是将常量加载到寄存器中作为示例,但不要忘记您可以使用 subi 和 sbci 操作码添加常量。例如,将 5 添加到 R18:R19:

SUBI R18,-5
SBCI R19,-1 # This isn't intuitive, but needs to be -1, not zero

从 R18:R19 中减去 5:

SUBI R18,5
SBCI R19,0 

【讨论】:

    猜你喜欢
    • 2019-08-07
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多