2

I am working on an assembly, techincally HLA (High Level Assembly), program. I need to convert this C code to assemvbly. Here is the assignment. Write an HLA Assembly language program that implements the following function:

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

This function should return into EAX the value of a % b based on a recursive approach. For simplicity sake, let's assume that both a and b will be greater than or equal to zero. By using recursion, you will be forced to manipulate the runtime stack. Base your solution on the following formulas:

Here is the provided C code:

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 );
}

Here is my HLA code:

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;

So the part of my code that works correctly is the first if block. For the second if block where result should be zero if b = 1, is that it just simply returns 1 instead of 0. For the 3rd conditional where if a is less than b I get this weird issues where it works for some combinations of numbers, but other time it just returns zero. for the else block where it is supposed to call the function recursively it just simply returns parameter a. `

ecain
  • 1,282
  • 5
  • 23
  • 54
  • I don't know all the rules for HLA, but your solution looks funny to me. In particular, you are "pop(a)"... where does that popped value go to? Is Generally when you write recursive assembly procedure, you want to keep everything in the registers or on top of the stack. The other thing that looks odd is pushing ECX and EBX on entry to the function which means you always do it in the "leaf" procedure of the call where it probably doesn't help you. If the purpose is to make ECX and EBX free to use, you can do that at the call site, avoiding the cost of doing this in the leaf procedure. – Ira Baxter Nov 12 '15 at 10:51
  • To be fair, how one manages saving/restoring registers is often a matter of *convention*. And if you don't care about performance, then you should use the "preferred convention" because that's what other readers of your code (your prof?) will expect. The fact that you are writing a recursive division already tells us that performance isn't the goal so maybe preferred convention is what you want. OTOH, the usual reason in practice that one writes assembler is for performance, so my personal radar is always focused that way. – Ira Baxter Nov 12 '15 at 10:55
  • Yes, I agree with what you are saying, but I am just following what I have to do for the assignment. – ecain Nov 13 '15 at 02:13
  • I also noticed a bug in the original algorithm: `a` and `b` are signed integers, so assume `a=-5, b=2`: `if (a < b)[YES] { result = a[=-5]; } which is obviously wrong(should be = -1). – zx485 Nov 13 '15 at 06:10
  • Yes, I noticed that as well, thank you. – ecain Nov 13 '15 at 18:19

1 Answers1

2

POP pops the last pushed value. You push first a then b, so you have to pop first b then a.

Change

pop(a);
pop(b);

to

pop(b);
pop(a);
rkhb
  • 14,159
  • 7
  • 32
  • 60