我想添加两个具有12个字节的数字,并将结果存储在16个字节的var中。我该怎么办?
$('#mylink').off('click');
我想我可以将数字1的前4个字节与数字2的其他前4个字节相加,依此类推..但我不知道如何在结果变量中串联结果。 如果需要,该如何携带? 此解决方案正确吗?
section .data
big_num1 dd 0x11111111, 0x22222222, 0x33333333
big_num2 dd 0xffffffff, 0x22222222, 0x33333333
section .bss
result_4word resd 4
答案 0 :(得分:2)
big_num1 dd 0x11111111, 0x22222222, 0x33333333 big_num2 dd 0xffffffff, 0x22222222, 0x33333333
由于x86是一种低端字节序的体系结构,因此数字的最低部分存储在内存中的最低地址处。对于 big_num1 ,第一个定义的dword(值为0x11111111)位于最低地址,因此是数字的最低部分。在普通数字表示中,这是右侧的内容。
big_num1 == 0x333333332222222211111111
big_num2 == 0x3333333322222222FFFFFFFF
您添加从右到左的相应数字,就像每个人在学校学到的一样。
在这些数字的十六进制表示形式中,有24位数字需要考虑。但是,由于该体系结构是32位的,因此我们可以很好地将3组8位数字组合在一起。
对于第一组,我们只需使用ADD
:
mov eax, [big_num1] ; 0x11111111
add eax, [big_num2] ; + 0xFFFFFFFF <-- This produces a carry
mov [result_4dword], eax ; 0x00000000
对于第二组,我们使用ADC
从前面的加法中提取可能的进位:
mov eax, [big_num1 + 4] ; 0x22222222
adc eax, [big_num2 + 4] ; + 0x22222222 + CF=1 <-- No new carry
mov [result_4dword + 4], eax ; 0x44444445
对于第3组,我们使用ADC
从前面的添加项中提取可能的进位:
mov eax, [big_num1 + 8] ; 0x33333333
adc eax, [big_num2 + 8] ; + 0x33333333 + CF=0 <-- No new carry
mov [result_4dword + 8], eax ; 0x66666666
这里的关键是,如果我们事先明确清除了进位标记,我们也可以将ADC
用于第一组:
clc
mov eax, [big_num1] ; 0x11111111
adc eax, [big_num2] ; + 0xFFFFFFFF + CF=0 <-- This produces a carry
mov [result_4dword], eax ; 0x00000000
现在我们可以编写一个包含3次迭代的循环,但是我们有请注意不要意外更改进位标志。这就是为什么我使用LEA
而不是ADD
来推进偏移量的原因。 DEC
也是不会破坏进位标志的指令。我更喜欢组合DEC ECX
JNZ ...
,因为它比LOOP ...
更好:
mov ecx, 3
xor ebx, ebx ; This additionally clears the carry flag
Again:
mov eax, [big_num1 + ebx]
adc eax, [big_num2 + ebx] ; Can produce a new carry flag
mov [result_4dword + ebx], eax
lea ebx, [ebx + 4] ; This does not clobber the carry flag
dec ecx ; This does not clobber the carry flag
jnz Again
如果在这3次加法之后还有一组进位,则必须在 result_4dword 的第4个双字中写一个 1 ,否则就必须写此处为 0 。因为 result_4dword 位于.bss部分中,所以您不应指望任何预设值(例如零!)!
setc cl
mov [result_4dword + ebx], ecx ; ECX=[0,1]
请注意,我已将 result_4word 更改为 result_4 d word 。更有道理...
答案 1 :(得分:1)
小学:
1234
+ 5678
========
开始填写
1
1234
+ 5678
========
2
4 + 8 = 12,所以2个携带一个。
在计算机上,您会 加一个= 4 + 8 adc b = 3 + 7 adc c = 2 + 6 adc d = 1 + 5
然后dcba包含您的结果,它可以根据需要缩放。 d,c,b,a可以是8位,16位,32位或64位,具体取决于指令集。如果有标志,大多数都具有add和adc,没有标志的则具有add和adc,然后您可以用各种方法合成它们,这些方法都不难……(使用32位寄存器/存储器将操作数分解为16位,则32位)现在添加位16是您要执行的操作,将其添加到下一个16位块中,需要进行一些移位和屏蔽,但是所有操作都相同,因为您可能有adc,那么您无需执行任何操作即可,adc,adc,adc ...,直到完成。
如果在启动前清除标志,则可以在循环中使用adc。
现在,如果您的变量未与处理器中的加法器对齐,则必须以某种方式对其进行合成。
针对同一问题的小学数学,现在您必须单独进行各列。
4
+ 8
====
12
,您必须手动将结果(12 >> 1)%9 = 1转换为底数10。
1
3
+ 7
====
11
然后
1
2
+ 6
====
9
这个数字为零
0
1
+ 5
====
6