Why isnt this simple bit of code working? (Newb)

Started by BenOJ, January 06, 2008, 06:24:34 PM

Previous topic - Next topic

BenOJ

OK I'm testing out DLL's in GoAsm and here's some code in c++ i did ((its VERRRY SIMPLE)

# define EXPORT __declspec (dllexport)

EXPORT void multiply(int a, int b )
{
       std::cout << a << "\n";
       std::cout << b << "\n";
}

Everything is fine then here's my ASM

CODE SECTION
;
START:

CALL test:1

PUSH -11,4
CALL test:2
RET


As far as I'm aware the RET call is supposed to pop everything off the stack. However when i run this it crashes... but if i change the RET to POPW AX,AX,AX,AX it runs fine.
Oh and could someone explain y it is that POP will not run ?? it keeps telling me to use POPW?
Thanks In advance - BEN


jorgon

Hi Ben

Welcome to the forum and to the world of Windows programming in assembler!

32-bit Windows works using the 32-bit registers, and AX is only half of the register EAX (AX is only 16-bits wide).
So if you try to use POP AX, this will be shown as an error.  You would use POP EAX to move into the EAX register the last dword (32-bits) on the stack.

Your use of POPW AX,AX,AX,AX is popping 4 words off the stack.  Since the stack works using dwords, we could also regard this as popping two dwords off the stack.  The instruction has the same overall effect as POP EAX,EAX except that it is slower to execute.

In assembler, RET does not pop everything off the stack.
It only pops one dword off the stack (it pops the address where the processor's instructions should continue to execute).

You are using RET at the end of your program to return execution to the Windows program which called your program when it started (the Windows caller).  Because you are using RET you need to ensure that the stack is in "equilibrium" at that time (if you used ExitProcess this would do this for you).

Your program is crashing because RET is not returning execution to the Windows caller but to somewhere else.  This is because the wrong thing is on the stack at the time when the RET is executed.

The reason for this is that your call to function ordinal 2 in test.dll is not putting the stack back into equilibrium.  The PUSH -11,4 is putting the stack out by two dwords.  Its equilibrium needs to be restored.

The fact that POPW AX,AX,AX,AX followed by RET works fine demonstrates that the above is the case.  The stack is being restored by the POPW instruction. 
As mentioned above POP EAX,EAX would look better or you could use the more traditional ADD ESP,8.  Or you could get your "C" program to clear the stack before it returns.

GoAsm also allows you to use "automated stack frames".  This is fully described in the GoAsm manual.  Such frames do restore the stack to equillibrium automatically.  But you don't need to use this for your simple program.


Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

BenOJ

Ah, ok thats much more clear now Thanks. The problem is im learning ASM at school and i guess what they teach us isnt as true in real life.
1 question though, do you know how to clear the stacks in c++ coz i havent got a clue ...
Also you said ADD ESP,8 ?

Does GoASM suport ADD and SUB because i couldnt see that anywhere in the manual? (Just i wrote a parser routene which uses ADD and SUB (psuedo) which i was going to convert to GOASM but it wasnt there  :red )
Thanks,
-BEN
ps- Thanks for the welcome !
EDIT:
1 last question -- sorry  :lol
How can i get interrupts to work they seemed to crash my program when i calll them?

+ i think i may hav found a bug
hello DD 3.4 comes out as a integer number doesnt seem to be using mantissa exponent coz thats the equivelent of a normal number

jorgon

Hi Ben

I believe you can ask "C" to clear up the stack if you use the __stdcall calling convention.

ADD ESP,8 would add 8 bytes (2 dwords) to the register ESP.  This register contains the current "stack pointer".  You can think of the stack as a plate warmer, with the top plate being the "top" of the stack, pointed to by ESP.   In other words ESP holds the address in memory of the top of the stack.  So if you use ADD ESP,8 all you are doing is moving the stack pointer down a bit, in fact ignoring the top two plates.  It's the same as POPping two plates off the stack.  In electronic terms each plate is a dword (32 bits of data, or 4 bytes).

Yes as you can see GoAsm supports ADD and SUB.  In fact GoAsm like most assemblers supports all the mnemonics.  There is no list of mnemonics in the GoAsm manual, since this information is well set out in other material.

As for interrupts, these only work in 16-bit assembler.  You can't use interrupts when programming with Windows.   Instead you would call a Windows API.  An API is a function in a Windows system DLL. 

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

BenOJ

Ok thanks a lot mate, youve been rrly helpfull.
All the best
-BEN

donkey

Hi BenOJ,

You can get an old but still extremely useful opcode help file here.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable