在 IA-32 架构上,如何在保留符号的同时对两个32 位有符号值求和/减去并将结果存储在64 位(EDX:EAX( 中?
对于此 32 位值:
A = 97
B = 232
C = 2147483600
D = 200
如何执行 C + A - D + B 并在汇编中返回 64 位值?
注意:C + A 的结果溢出 32 位注册表。
在将 C 添加到 A 后,我尝试使用adc函数将进位添加到 edx 中,但由于它是有符号的,它并没有像我假装的那样做。
我为 C+A 尝试了什么,但它没有保留符号:
#Prologue
pushl %ebp
movl %esp, %ebp
#Body
movl $0, %edx
movl $0, %ecx
movl $0, %eax
movb 8(%ebp), %al #
movsx %al, %eax #move with sign extention to 32 bit eax
addl 16(%ebp), %eax #adding C + A
adcl $0, %edx
如果 C 是 -97 而 A 是 -2147483600(对于负值(,我也有同样的问题。
最好的方法是在使用CDQ
进行相应的计算之前将 32 位有符号值扩展到 64 位有符号值:
.section .data
fmt: .string "Result: %llin"
.section .text
.globl main
main:
pushl $97 # A
pushl $232 # B
pushl $2147483600 # C
pushl $200 # D
call do_it
add $8, %esp
push %edx
push %eax
push $fmt
call printf
add $8, %esp
pushl $0
call exit
do_it:
pushl %ebp # Prologue
movl %esp, %ebp
mov 12(%ebp), %eax # C
cdq
mov %edx, %edi # X = C
mov %eax, %esi
mov 20(%ebp), %eax # A
cdq
add %eax, %esi
adc %edx, %edi # X += A
mov 8(%ebp), %eax # D
cdq
sub %eax, %esi # X -= D
sbb %edx, %edi
mov 16(%ebp), %eax # B
cdq
add %eax, %esi
adc %edx, %edi # X += B
mov %edi, %edx # RETURN = X
mov %esi, %eax
leave # Epilogue
ret