我试图了解如何在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
。此外,返回值位于相同的寄存器中。 r18
和r19
存储y
的较低和较高字节。
我的问题是:在肯定的情况下r18
和r19
得到16
和39
(39*256+16==10000
),但为什么会得到-40
在否定的情况下,而不是-39
?
一般如何表示带符号的多字节数字以及如何添加它们?
答案 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相同的助记符。)