【问题标题】:How does signed 16bit addition work in avr-gcc?签名的 16 位加法在 avr-gcc 中如何工作?
【发布时间】:2016-01-30 22:29:42
【问题描述】:

我正在尝试了解如何在 avr 程序集中的 2 个 16 位数字之间进行有符号加法。

鉴于此 C 代码:

#include <stdbool.h>

int16_t my_fun(const int16_t x, bool is_positive){
    const int16_t y = 10000 * (is_positive? 1 : -1);
    return x + y;
}

avr-gcc 输出(简化为更具可读性):

my_fun:
    cpse r22,r1
    rjmp positive
    ldi r18,-16
    ldi r19,-40
    rjmp add_them
positive:
    ldi r18,16
    ldi r19,39
add_them:
    add r24,r18
    adc r25,r19
    ret

我知道x 的低字节在r24 中,高字节在r25 中。此外,返回值在相同的寄存器中。 r18r19 存储 y 的低字节和高字节。

我的问题是:在积极的情况下,r18r19 得到 1639 (39*256+16==10000) 但为什么在消极的情况下他们得到 -40 而不是 -39? 带符号的多字节数一般如何表示,如何相加?

【问题讨论】:

  • -40 是 216 无符号,-16 是 240 无符号,这给出 55536 无符号,即 -10000 有符号。或者换句话说,-10000 是 0xD8F0 十六进制,它具有给定的低字节和高字节。见two's complement。加法本身的工作原理相同。
  • 加法和减法没有有符号或无符号的概念。乘法和除法,当然,但加法和减法不是。部分互补之美。

标签: assembly avr avr-gcc


【解决方案1】:

扩展精度整数存储在块中(通常是机器字大小,AVR 为 1B,x86-32 为 4B。)。 GMP (the gnu multi-precision library) 称这些块为“肢体”。

在您的情况下,您在寄存器中拥有两个数字的所有块(在 ldi 指令之后)。它们可以像数组或结构一样存储在内存中。

由于进位/借位通过加减法从 LSB 传播到 MSB,用于添加它们的机器指令序列以设置进位标志(或不设置)的 LSB 上的普通 add 开始,然后是 adc (add-with-carry)所有其余块的指令。 adc 读写进位标志。

add / adc 与您在 x86 上看到的序列相同,用于在 32 位模式下添加 64 位数字,或在 64b 模式下添加 128b 数字。 (x86 对这些insns 使用与AVR 相同的助记符。)

【讨论】:

    猜你喜欢
    • 2012-12-19
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多