如何在avr-gcc中签名16位加法工作?

时间:2016-01-30 22:29:42

标签: assembly avr avr-gcc

我试图了解如何在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得到163939*256+16==10000),但为什么会得到-40在否定的情况下,而不是-39? 一般如何表示带符号的多字节数字以及如何添加它们?

1 个答案:

答案 0 :(得分:0)

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

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

由于进位/借位在加法和减法中从LSB传播到MSB,因此用于添加它们的机器指令序列以LSB上的正常add开始,其设置进位标志(或不是),然后是{所有其余块的{1}}(附加携带)指令。 adc读取并写入进位标志。

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