2015-11-12 4 views
2

Je travaille sur un programme d'assemblage, techniquement HLA (High Level Assembly). J'ai besoin de convertir ce code C en assemvbly. Voici l'affectation. Ecrivez un programme de langage HLA Assembly qui implémente la fonction suivante:Programme d'assemblage par division récursive

procédure recursiveModulo (a: int32; b: int32); @nodisplay; @pas de cadre;

Cette fonction doit retourner dans EAX la valeur de% b basée sur une approche récursive. Par souci de simplicité, supposons que a et b seront supérieurs ou égaux à zéro. En utilisant la récursivité, vous serez forcé de manipuler la pile d'exécution. La base de votre solution sur les formules suivantes:

Voici le code C fourni:

int recursiveModulo(int a, int b) 
{ 
    int result = 0; 
    if (a == 0 || b == 0) 
    { 
    result = 0; 
    } 
    else if (b == 1) 
    { 
    result = 0; 
    } 
    else if (a < b) 
    { 
    result = a; 
    } 
    else 
    { 
    result = recursiveModulo(a-b, b); 
    } 
    return(result); 
} 

Voici mon code HLA:

program RecursiveDivision; 
#include("stdlib.hhf"); 
static 
iDataValue1 : int32 := 0; 
iDataValue2 : int32 := 0; 

procedure recursiveModulo(a: int32; b : int32); @nodisplay; @noframe; 
static 
returnAddress : dword; 


begin recursiveModulo; 

pop(returnAddress); 
pop(a); 
pop(b); 
push(returnAddress); 
push(ECX); 
push(EBX); 


cmp(a, 0); 
je equal; 
jmp checkb; 

checkb: 
cmp(b, 0); 
je equal; 
jmp b1; 

b1: 
cmp(b, 1); 
je equal; 
jmp alessb; 

equal: 
mov(0, EAX); 
jmp ExitSequence; 

alessb: 
mov(a, EBX); 
cmp(b, EBX); 
jg resulta; 
jmp recursive; 

resulta: 
mov(a, EAX); 
jmp ExitSequence; 

recursive: 
mov(a, ECX); 
sub(b, ECX); 
push(ECX); 
push(b); 
call recursiveModulo; 
jmp ExitSequence; 

ExitSequence: 
pop(ECX); 
pop(EBX); 
ret(); 




end recursiveModulo; 

begin RecursiveDivision; 

stdout.put("Give me A",nl); 
stdin.get(iDataValue1); 
stdout.put("Give me B",nl); 
stdin.get(iDataValue2); 
push(iDataValue1); 
push(iDataValue2); 
call recursiveModulo; 
stdout.puti32(EAX); 


end RecursiveDivision; 

Ainsi, la partie de mon code qui fonctionne correctement est la d'abord si le bloc. Pour le second bloc if où le résultat devrait être nul si b = 1, c'est qu'il renvoie simplement 1 au lieu de 0. Pour le 3ème conditionnel où si a est inférieur à b j'obtiens ces problèmes bizarres où cela fonctionne pour certaines combinaisons de nombres , mais à un autre moment, ça revient juste à zéro. pour le bloc else où il est supposé appeler la fonction récursivement, il retourne simplement le paramètre a. `

+0

Je ne connais pas toutes les règles de HLA, mais votre solution semble drôle pour moi. En particulier, vous êtes "pop (a)" ... où va cette valeur éclatée? Généralement, lorsque vous écrivez une procédure d'assemblage récursif, vous voulez tout conserver dans les registres ou au-dessus de la pile. L'autre chose qui semble étrange est de pousser ECX et EBX à l'entrée de la fonction, ce qui signifie que vous le faites toujours dans la procédure "feuille" de l'appel où cela ne vous aide probablement pas. Si le but est de rendre ECX et EBX libres d'utiliser, vous pouvez le faire sur le site d'appel, en évitant le coût de faire cela dans la procédure feuille. –

+0

Pour être juste, comment gérer les registres de sauvegarde/restauration est souvent une question de * convention *. Et si vous ne vous souciez pas de la performance, alors vous devriez utiliser la "convention préférée" car c'est ce à quoi s'attendent les autres lecteurs de votre code (votre prof?). Le fait que vous écrivez une division récursive nous dit déjà que la performance n'est pas l'objectif, donc peut-être la convention préférée est ce que vous voulez. OTOH, la raison habituelle dans la pratique que l'on écrit assembleur est pour la performance, donc mon radar personnel est toujours concentré de cette façon. –

+0

Oui, je suis d'accord avec ce que vous dites, mais je suis juste ce que je dois faire pour la mission. – ecain

Répondre

2

POP affiche le dernier valeur push. Vous poussez d'abord a puis b, donc vous devez d'abord apparaître b puis a.

changement

pop(a); 
pop(b); 

à

pop(b); 
pop(a);