Problems accessing the stack.

Programming, for all ages and all languages.
Post Reply
Neptune

Problems accessing the stack.

Post by Neptune »

I seem to be accessing the stack incorrectly here. Basically, what I am trying to do is load the address of a null-terminated string that was passed onto the stack into edx, loop through and print each character. For some reason, I cannot get it to work. Here is the call:

Code: Select all


 entry:

push msg
call print
add esp, 0x04

xor eax, eax
ret


And here is the function:

Code: Select all


 print:

push ebx ; preserve, C-style
lea edx, [esp+8]

 printloop:

mov al, byte [edx]
or al, al
jz endprint
mov ah, 0x0e ; BIOS print-char subservice
mov bx, 0x0007 ; text attribute
int 0x10 ; BIOS video service
inc edx
jmp printloop
 
 endprint:

pop ebx 
ret

Tim

Re:Problems accessing the stack.

Post by Tim »

You need MOV, not LEA. Currently you are printing the contents of the stack. You want to print the contents of a string, a pointer to which is on the stack.
Neptune

Re:Problems accessing the stack.

Post by Neptune »

OK, but the syntax would be the same - correct? ie:

mov edx, [esp+8]
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Problems accessing the stack.

Post by Candy »

sebastian wrote: OK, but the syntax would be the same - correct? ie:

mov edx, [esp+8]
in theory, yes

In practice, it should be

mov edx, [esp+4]

because you want the msg.
Neptune

Re:Problems accessing the stack.

Post by Neptune »

I guess the real problem is just that I do not know how to access data from the stack properly. I simplified the program a bit in order to narrow down the possibilities, but the output is still erroneous.

(assembler: nasm, 32 bit environment)

entry:

push msg
call print
add esp, 4
ret

print:

lea edx, [esp+8]
push edx
call _printf
add esp, 4
ret


I even changed 'lea' to 'mov', but that didn't work either. Can someone show me a working example of using the stack to pass strings?
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Problems accessing the stack.

Post by Candy »

Code: Select all

entry:
push msg
call print
add esp, 4
ret

 print:
 
mov edx, [esp+4]
push 0
push edx
call _printf
add esp, 8
ret

ps: are you sure you want to ret? there's nothing to catch you, probably...
Neptune

Re:Problems accessing the stack.

Post by Neptune »

Thanks a million, Candy! I've been toiling with that for several days now - whew! :)

One more question:

>> mov edx, [esp+4]

I thought that when using 'call', the return address is pushed onto the stack, so that upon function entry esp+4 would contain the return address and the parameter I passed would be at esp+8?
Neptune

Re:Problems accessing the stack.

Post by Neptune »

>> are you sure you want to ret? there's nothing to catch you, probably...

What do you mean? I thought you always has to ret (from 'main', to the OS, and from frunctions, to the caller)?
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Problems accessing the stack.

Post by Candy »

sebastian wrote: >> mov edx, [esp+4]

I thought that when using 'call', the return address is pushed onto the stack, so that upon function entry esp+4 would contain the return address and the parameter I passed would be at esp+8?
It is on the stack, but the stack pointer points to the last thing you put on it. So, [esp] would be the return address, and [esp+4] is the address of the first variable. When you push something on in your routine (say, the old base pointer) [esp] would be the base pointer, [esp+4] would be the return address and [esp+8] would be the first argument.

For completeness (if you're using 32-bit linux systems, you can ignore it):

In windows parameters are passed by __stdcall. IIRC, that meant that the LAST parameter is [esp+8] after pushing the base pointer.
On any non-32-bit system the parameters are not 4 bytes. On any system they're [?sp + n] where ?sp is the name of the current stack pointer (sp, esp, rsp) and n is the number of bytes that hold those amounts of bits (2, 4, 8).
64-bit arguments on a 32-bit system (and so on for the 16-bit systems etc.) are passed in 2 arguments rather than one. Count those doubles too. They're passed in little-endian order, so the first n-byte word is the smaller half, and the last one is the larger half.
>> are you sure you want to ret? there's nothing to catch you, probably...

What do you mean? I thought you always has to ret (from 'main', to the OS, and from frunctions, to the caller)?
Sorry, wrong forum. Thought you were doing osdev (barely any ASM programming otherwise) and if you were, there's no OS below you. That's why I said that.
Neptune

Re:Problems accessing the stack.

Post by Neptune »

Ah, ok, I think I've got it now.

>> Thought you were doing osdev

I am, actually, just thought you were referring to normal assembly - funny. ;D

For now I'm just jumping to the BIOS reboot routine at 0xffff:0000 at the end of 'main'.

Anyway, thank you for clearing that up for me - I was really stuck!

Cheers.
Post Reply