x86添加A + B-C + D以64位返回

时间:2017-10-17 19:20:20

标签: assembly x86

你好,我在大学时遇到问题。 我们正在学习x86 asm,到目前为止,我花了很多时间才能正确理解代码。 我试图以签名方式添加+ b -c + d并返回64位值(很长)

问题是,代码实际上有效,我不明白它为什么会这样做。 以下变量在main.c中声明为globals

 char op8 = 0;
 short op16 = 0;
 int op32a=0,op32b=0;

int main() {

// (op1 + op2) - op3 + op4
op8 = 127;
op16 = 30767;
//op8 + op16 = 30894
op32a = 1;
op32b = 2147483647;
//(op8 + op16 - op32a) =30893;
//30893 + 2147483647 = 2146514540
long long result = specialsum();

printf("%lld\n",result);

}

.section .data
.global op8
.global op16
.global op32a
.global op32b
.section .text
.global specialsum
specialsum:
# prologue
pushl %ebp
movl %esp,%ebp

# inicializar tudo a zero
movl $0,%eax
movl $0,%ebx
movl $0,%ecx
movl $0,%edx

# carregar os valores para os registos
mov op16,%ax
mov op8,%bl

# adicionar a eax o ebx
# A + B
add %bx,%ax
adc $0,%eax

# remover op32a a eax
# (A+B) - C
movl op32a,%ebx
subl %ebx,%eax

# (A+B-C) + D
movl op32b,%ebx
addl %ebx,%eax


jmp fim

fim:

movl %ebp,%esp
popl %ebp

# o retorno de 64 bits é
# EDX:EAX
# H:L
ret 

以下代码实际产生正确的输出。 但我虽然在最后一次操作中添加了adc $ 0,%edx所以它会返回一个实际的64位数字

# (A+B-C) + D
movl op32b,%ebx
addl %ebx,%eax
adc $0,%edx

我不明白为什么它产生正确的输出,即使我没有将进位添加到edx

有人可以解释一下吗?

1 个答案:

答案 0 :(得分:1)

您唯一的测试用例会产生2146514540的结果,该结果为正但小于2 ^ 31-1,因此EDX = 0是正确的。你做零EDX(用mov而不是通常的xor %edx,%edx),所以你的固定常数上半部分恰好对你测试的输入是正确的。

如果你测试的是需要负面结果的东西,或者大于2 ^ 31-1的正面结果,你会发现你的函数中存在一些错误。

其他测试用例:op16 = 0xffop8 = 1或更高,因此add %bx,%ax会产生一个进位,而adc $0,%eax会产生垃圾。 在您查看注册值时,使用调试器单步执行代码。

提示,加载movswl op16, %eax; cltdop16签名延伸到edx:eax