0

Hello i'm struggling with a problem in college. We are learning x86 asm, and so far i have taken many hours to understand properly the code. I'm trying to add a+b -c +d in a signed fashion and returning as a 64bit value (long long)

Problem is, the code actually works and i don't understand why it does. The following variables are declared in main.c as 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 

The following code actualy produces the right output. But i though that i add adc $0,%edx in the last operation so it would return an actual 64bit number

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

I don't understand why it produces the right output even though i'm not adding the carry to edx

Can someone explain?

frost
  • 66
  • 7

1 Answers1

1

Your only test-case produces a result of 2146514540, which is positive but less than 2^31-1, so EDX=0 is correct. You do zero EDX (with a mov instead of the usual xor %edx,%edx), so your fixed-constant upper half happens to be correct for the inputs you tested with.

If you tested with something that required a negative result, or a positive result greater than 2^31-1, you would find some of the bugs in your function.

Other test cases: op16 = 0xff and op8 = 1 or higher, so add %bx,%ax will produce a carry and adc $0,%eax will produce garbage. Single-step through your code with a debugger while you watch register values.

Hint, load with movswl op16, %eax ; cltd to sign-extend op16 into edx:eax.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847