0

I need help with this push pop situation. I'm trying to write an HLA Assembly language program that implements a function which correctly identifies when all four parameters are the same and returns a boolean value in AL (1 when all four values are equal; 0 otherwise).

Here is my code so far:

program same;
#include("stdlib.hhf");
static
w : int16 :=0;
x : int16 :=0;
y : int16 :=0;
z : int16 :=0;
temp : int16;

// Function theSame //
procedure theSame(w:int16; x:int16; y:int16; z:int16); @nodisplay; @noframe;
static
returnAddress : dword;
similar: int16;

begin theSame;
pop(returnAddress);
pop(similar); // Padding - stacking must be 32 bit align
pop(z);
pop(y);
pop(x);
pop(w);
push(returnAddress);

stdout.put( "w = ", w, nl );
stdout.put( "x = ", x, nl );
stdout.put( "y = ", y, nl );
stdout.put( "z = ", z, nl );


stdout.put( "cmp w x ", nl );
mov(w,AX);
cmp(AX,x);
je Equal;
jne Notequal; // (w==x)

stdout.put( "cmp x y ", nl );

mov(x,AX);
cmp(AX,y);
je Equal;
jne Notequal; // (x==y)

stdout.put( "cmp y z ", nl );

mov(y,AX);
cmp(AX,z);
je Equal;
jne Notequal; // (y==z)

stdout.put( "cmp z w ", nl );

mov(z,AX);
cmp(AX,w);
je Equal;
jne Notequal; // (w==z)

Equal:
stdout.put( "equal", nl );
mov(1,AX);
push(similar); // padding
jmp ExitSequence;

Notequal:
stdout.put( "not equal", nl );
mov(0,AX);
push(similar); // padding
jmp ExitSequence;

ExitSequence:
ret();

end theSame;

begin same;
stdout.put("Feed Me W: ");
stdin.get(w);
push(w);
stdout.put("Feed Me X: ");
stdin.get(x);
push(x);
stdout.put("Feed Me Y: ");
stdin.get(y);
push(y);
stdout.put("Feed Me Z: ");
stdin.get(z);
push(z);

call theSame;
cmp(AX, 1);
je YESEQUAL;
jmp NOEQUAL;

YESEQUAL:
stdout.put("True", nl);
jmp EndProgram;


NOEQUAL:
stdout.put("False", nl);
jmp EndProgram;

stdout.newln();
EndProgram:

end same;

However, the output came out to this:

Input:

Feed me W: 8
Feed me X: 7
Feed me Y: 6
Feed me Z: 5

Output:

W: -165
X: 8
Y: 7
Z: 6
cmp w x
not equal

Is there a reason why it's the same value to each other? Confuse on how push and pop works. Thank you.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    Please post program output as text, not a picture. [Edit] your question to fix this please. – fuz Jul 25 '21 at 20:29
  • You don't need any push/pop to access args on the stack, and in fact should avoid doing that. Leave your return address where it is, and access args relative to ESP. x86 has enough registers to do this easily, you don't need static storage (global variables) either. – Peter Cordes Jul 25 '21 at 21:02
  • @PeterCordes, thank you, what was the purpose behind push/pop. – retrofusion Jul 25 '21 at 21:26
  • 1
    push/pop is useful for saving/restoring registers at the start/end of a function respectively. Push is also useful for passing stack args. But remember that stack memory is still just RAM and you can (and should) do random access to it. – Peter Cordes Jul 26 '21 at 00:49
  • If you look at how compilers use push/pop, when compiling C ([How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) / [What are callee and caller saved registers?](https://stackoverflow.com/a/56178078)), that's a pretty good guide to when you should use push/pop. – Peter Cordes Jul 26 '21 at 01:05

1 Answers1

2
pop(similar); // Padding - stacking must be 32 bit align

Apparently you need to remove this pop(similar) instruction. If you leave it, it obtains the value of the z argument. And makes w get garbage from the stack! Don't forget to also remove the push(similar) instructions.

Layout of your stack on entry:

x  x  5  6  7  8  -165
----
^     ^  ^  ^  ^
|     z  y  x  w  all 4 words
dword return address
pop(returnAddress);
pop(z);
pop(y);
pop(x);
pop(w);
push(returnAddress);
Sep Roland
  • 33,889
  • 7
  • 43
  • 76