2017-10-17 5 views
-1

Bonjour, je suis aux prises avec un problème à l'université. Nous apprenons x86 asm, et jusqu'ici j'ai pris beaucoup d'heures pour comprendre correctement le code. J'essaie d'ajouter un + b -c + d d'une manière signée et de revenir en tant que valeur 64bit (long long)x86 Ajouter A + B-C + D retourner en 64bits

Le problème est, le code fonctionne réellement et je ne comprends pas pourquoi il le fait. Les variables suivantes sont déclarées dans main.c comme 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 

Le code suivant produit la sortie droite actualy. Mais je pensais que j'ajouter adc $ 0,% edx dans la dernière opération il renvoyait un nombre de 64 bits réelle

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

Je ne comprends pas pourquoi il produit la sortie à droite, même si je ne suis pas d'ajouter la porter à edx

Quelqu'un peut-il expliquer?

+0

Et si je voulais rendre le programme plus robuste, où devrais-je ajouter les contrôles de débordement? – frost

+0

Quelle partie ne comprenez-vous pas? – Neo

+0

si C est un nombre négatif vraiment élevé (a + b) - (- C) Devrait-il déborder? Comment ajouter ce grand nombre à D et le diviser en EDX: EAX – frost

Répondre

1

Votre seul test-case produit un résultat de , positif mais inférieur à 2^31-1, EDX = 0 étant correct. Vous faites zéro EDX (avec un mov au lieu de xor %edx,%edx), de sorte que votre moitié supérieure constante constante est correcte pour les entrées que vous avez testées.

Si vous avez testé avec quelque chose qui nécessite un résultat négatif, ou un résultat positif supérieur à 2^31-1, vous trouverez certains des bugs dans votre fonction.

Autres cas de test: op16 = 0xff et op8 = 1 ou plus, de sorte add %bx,%ax produiront un report et adc $0,%eax produiront des déchets. Parcourez votre code avec un débogueur pendant que vous regardez les valeurs de registre.

Indice, charger avec movswl op16, %eax; cltd pour signer-étendre op16 en edx:eax.