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に保存したい。
その背後にある「数学」について:それは10進法とまったく同じです:
1 桁の数字を 2 つ足す場合、2 つのケースを考慮する必要があります。2 つの合計が新しい 1 桁の数字 (5+4 = 9) になるか、「オーバーフロー」が発生して別の数字が必要になります (5+6 = 11)。任意の 2 つの数値 (基数は 10、2、256 など) のn
桁長の場合、2 つの合計は常に最小桁数の 2 倍よりも小さくなることに注意してくださいn+1
。leti
とj
be は、たとえば長さ 1 の数値 (基数 10) です。つまり、両方とも と の間0
にあり9
ます。10
length の最小数と同様n+1 = 2
に、それらの合計は常に より小さくなり2 x 10
ます。
2 つの数値を加算する場合、オーバーフローが発生しない場合と、ちょうど 1 のオーバーフローが発生する場合があります。キャリー ビットには、最後の算術演算からのこのオーバーフローが格納されます。0か1です。
したがって、それぞれ 4x 8 ビットの 2 つの数値 (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";
}
かなり簡単な操作。最初の演算には 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 オペコードを使用して定数を追加できることを忘れないでください。たとえば、R18:R19 に 5 を追加するには:
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