我们如何使用添加32位算术两个64位数字??

有帮助吗?

解决方案

第一添加至少显著字节,保持进位。添加考虑从最低有效位的进位的最显著字节数:

; x86 assembly, Intel syntax
; adds ecx:ebx to edx:eax
add eax, ebx
adc edx, ecx

其他提示

考虑如何使用添加1位的算术两个2位数字。

 42
+39
---

首先,添加右侧立柱。 (其中“一”或“单元”)。 2 + 9是11。11“溢出”您的1位算术运算,所以你必须“携带” 10。

 1
 42
+39
---
  1

现在你把左边的“十位”一栏,包括随身携带。 1 + 4 + 3 = 8。

 1
 42
+39
---
 81

图8是小于10,所以进位。你就大功告成了。

刚刚发生了什么?当你说一个号码是“42”(在基体10)你真的是

4*10+2

或者,等价地,

4*10^1+2*10^0

(当我说“一个^ B”,如“10 ^ 1”,我的意思是“一个上升到b'th功率”:一个自乘b乘以10 ^ 0是1 10 ^ 1是10. 10 ^ 2是10×10 = 100 ......)

在添加 “42” 和 “39” 你说

4*10+2+3*10+9

其等于

(4+3)*10+(2+9)*1
(4+3)*10+(11)*1
(4+3)*10+(1*10+1)*1

现在,因为“11”是不是一个有效一位数,则需要从的那些携带10,将其变成1中的十位。

(4+3)*10+(1)*10+(1)*1
(4+3+1)*10+(1)*1
(8)*10+(1)*1

这是81。

那么,为什么我一直在谈论这个,而不是你的问题,约64位数字和32位的算术?因为他们实际上是完全一样的!

一个数字范围从0到9的“32比特数”的范围从0到2 ^ 32-1。 (假设它是无符号的。)

因此,而不是在基体10的工作,让我们在基座2 ^ 32工作。在基体2的32次方,我们写出2 ^ 32作为10.如果在基座2 ^ 32写一个64位的数,这将是

(x)*10+y

其中x和y是符号0和2 ^ 32-1之间的数字。这些符号是位串。

如果要添加两个64位的数,其分解在基体2 ^ 32为:

 a_1*10+a_0
+b_1*10+b_0

现在你将它们添加在基地2 ^ 32你添加它们在基地10完全相同的方式 - 只是,而不是使用数字算术加入您添加使用32位运算

如何分割一个64位的数为两个32位数字A_1和A_0?由2 ^ 32分割。不要在浮点,但integerwise - 你在哪里得到的股息和余数。被除数是A_1,余数是A_0。

不幸的是,需要64位算术。然而,典型地是A_1的“最显著一半”,所以,在C风格语法:

a_1=(a >> 32)
a_0=(a & 0xFFFFFFFF)

其中>>是右位位移和&是按位和

通常,如果你不能做64位加法,一个“64比特数”实际上是两个32位的数字和A_1 A_0。你不会有一个uint64_t中,如果你不能做到uint64_t中算术!

这一切都假定你正在做的无符号运算,但是处理的迹象是很容易从这里开始。

先前发布的C代码是不必要的冗长:

unsigned a1, b1, a2, b2, c1, c2;

c1 = a1 + b1;
c2 = a2 + b2;

if (c1 < a1)
    c2++;

在“A1”的“如果”可与“B1”,以及代替。 上溢,C1将小于两个a1和b1。

如果该64位数字是(a <子> 2 ,一个<子> 1 )和(b <子> 2 ,B <子> 1 ),其中 X <子> 2 取的高32位作为无符号,和 X <子> 1 是低作为无符号的32位,则两数之和在下面给出。

c1 = a1 + b1

c2 = a2 + b2

if (c1 < a1 || c1 < b1)
   c2 += 1

它看起来像这样

/* break up the 64bit number into smaller, 16bit chunks */
struct longint { 
    uint16 word0; 
    uint16 word1;
    uint16 word2;
    uint16 word3;
};

uint16 add(longint *result, longint *a, longint *b)
{
    /* use an intermediate large enough to hold the result
       of adding two 16 bit numbers together. */
    uint32 partial;

    /* add the chunks together, least significant bit first */
    partial = a->word0 + b->word0;

    /* extract thie low 16 bits of the sum and store it */
    result->word0 = partial & 0x0000FFFF;

    /* add the overflow to the next chunk of 16 */
    partial = partial >> 16 + a->word1 + b->word1;
    /* keep doing this for the remaining bits */
    result->word1 = partial & 0x0000FFFF;
    partial = partial >> 16 + a->word2 + b->word2;
    result->word2 = partial & 0x0000FFFF;
    partial = partial >> 16 + a->word3 + b->word3;
    result->word3 = partial & 0x0000FFFF;
    /* if the result overflowed, return nonzero */
    return partial >> 16;
}

实际的硬件不使用32位来一次增加16位,只有一个随身携带的额外位曾经需要另外,几乎所有的CPU有当加法运算溢出进位状态标志,因此,如果您使用的是32位的CPU,可以在两个32位操作添加64个操作数。

几乎每一个处理器有进位,并附加与携带的操作,你只在乎,如果你在汇编语言编程。如果您使用的是更高的语言,编译器转储出完全一样的附加与携带的操作。我的AVR-GCC给了我这个增加两个16位数字时 - 的AVR 8位 - 但相同的概念也适用于更高的处理器。

给出的数字是在寄存器R1:R2和R3:R4:

ADD R2,R4 ; first add the two low-bytes, result stored into R2
ADC R1,R3 ; then the two high-bytes and the carry bit, into R1

在结果存储到R1:R2

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top