can't print string when passed on stack
can't print string when passed on stack
I'm trying to modify OS code I downloaded. The code prints a message and I want it to be a function so I can print other messages with it. I pass the address of the string on the stack and it won't work, but it does work if I just use message instead of esp+8. Please help. Thanks, Josh
ORG 0xFF800000
BITS 32
SEGMENT .data
message db "Assembly Kernel with function calls loaded",0
SEGMENT .text
; main kernel
start:
push dword message
call print_msg
end:
jmp short $ ;Hang here
; functions
print_msg:
push bp
mov bp,sp
cld ;new - clear direction flag to ensure direction registers work correctly for lodsb and stosw
mov edi, 0xB8000 ; move addr of vid mem to edi
mov esi, [esp+8]
mov ah, 7 ;Text attribute
.again: lodsb
stosw
test al, al
jnz .again
mov sp,bp
pop bp
ret
ORG 0xFF800000
BITS 32
SEGMENT .data
message db "Assembly Kernel with function calls loaded",0
SEGMENT .text
; main kernel
start:
push dword message
call print_msg
end:
jmp short $ ;Hang here
; functions
print_msg:
push bp
mov bp,sp
cld ;new - clear direction flag to ensure direction registers work correctly for lodsb and stosw
mov edi, 0xB8000 ; move addr of vid mem to edi
mov esi, [esp+8]
mov ah, 7 ;Text attribute
.again: lodsb
stosw
test al, al
jnz .again
mov sp,bp
pop bp
ret
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:can't print string when passed on stack
one thing that troubles me is, if you're under a 32 bits environment, why do you only "mov bp,sp" and not "mov ebp, esp" ?
Re:can't print string when passed on stack
Is it just me, or is it so that Ebp isn't even used? Nor is Esp modified... So neither of them should be needed to be saved...
Hm... Esp+8... The return address... and Bp... and the parameter... can it have something to do with that the stack grows downwards?
The pushing of the parameter is correct... it should push the address... and the moving to Esi is correct too... at least the syntax is...
Hm... Wait a sec... Bp is only 2 bytes... You know that do you?
Hm... Esp+8... The return address... and Bp... and the parameter... can it have something to do with that the stack grows downwards?
The pushing of the parameter is correct... it should push the address... and the moving to Esi is correct too... at least the syntax is...
Hm... Wait a sec... Bp is only 2 bytes... You know that do you?
Re:can't print string when passed on stack
What is the base of the DS and SS segments? they should be the same. From the code posted, you didn't do that.
Re:can't print string when passed on stack
>>one thing that troubles me is, if you're under a 32 bits environment, why do you only "mov bp,sp" and not "mov ebp, esp" ?
Thanks, that did it.
Thanks, that did it.
Re:can't print string when passed on stack
But why are Ebp and Esp saved? They aren't used, are they?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:can't print string when passed on stack
it's a C convention, and if you want your first argument to be at [ebp+8] (which should be preffered over [esp+8]), you must push something after the return address.
Despite i'm not sure that's the way it will work, i fear that "push bp" only increased the stack pointer by 2 rather than by 4, which messed things up ...
From intel manuals:
Despite i'm not sure that's the way it will work, i fear that "push bp" only increased the stack pointer by 2 rather than by 4, which messed things up ...
From intel manuals:
this sounds a bit contradictory, but the last sentence makes me think i wasn't wrong ...The address-size attribute of the stack segment determines the stack pointer size (16 bits or 32 bits), and the operand-size attribute of the current code segment determines the amount the stack pointer is decremented (2 bytes or 4 bytes).
...
Pushing a 16-bit operand when the stack addresssize attribute is 32 can result in a misaligned the stack pointer (that is, the stack pointer is not aligned on a doubleword boundary).
Re:can't print string when passed on stack
It's a C convention, it's called a frame-pointer, it helps debugging (you can trace stack back easier) which is one reason C compilers do it, and it allows access to parameters even if dynamic allocations (of varying size) are done on stack without any extra runtime calculations.Peter_Vigren wrote: But why are Ebp and Esp saved? They aren't used, are they?
Except for some special cases (I think the last one is one, and there might be some other) gcc allows you to drop frame pointers by using -fomit-frame-pointer. No all architechtures allow debugging without it, but i386 does, so it's a common optimization.
I don't know if other compilers have such a switch.. but then again writing a kernel debugger (or panic handler with stack trace) is much easier if you keep the frame pointers, since you can always get previous ebp from stack at ebp, which also allows you to easily find the return address..
Re:can't print string when passed on stack
I noticed that this function still has a subtle bug in it, which is in fact related to Peter's query: it uses [tt][[ESP+8]][/tt] as the argument offset, rather than [tt][[EBP+8]][/tt]. While this does indeed work as it is (since the stack isn't otherwise used), it would break if any stack-related changes were made in the code.
Also, assuming that the C code is compiled under gcc, then technically the [tt]EBX[/tt], [tt]ESI[/tt] and [tt]EDI[/tt] registers should be saved as well; while it is acceptable to let [tt]EBX[/tt] slide in this particular case, since it isn't being used, not preserving [tt]ESI[/tt] and [tt]EDI[/tt] could lead to serious problems in your C code.
If you are using a different C compiler (Borland C, lcc32, etc.), then you'd want to check the calling convetions used by your compiler, though they are probably similar if not the same.
Also, assuming that the C code is compiled under gcc, then technically the [tt]EBX[/tt], [tt]ESI[/tt] and [tt]EDI[/tt] registers should be saved as well; while it is acceptable to let [tt]EBX[/tt] slide in this particular case, since it isn't being used, not preserving [tt]ESI[/tt] and [tt]EDI[/tt] could lead to serious problems in your C code.
If you are using a different C compiler (Borland C, lcc32, etc.), then you'd want to check the calling convetions used by your compiler, though they are probably similar if not the same.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:can't print string when passed on stack
as a generic solution, encapsulate your ASM code within
Code: Select all
push ebp
mov ebp,esp
pushad
... asm code accesses arguments through [ebp+8], [ebp+12] ...
popad
pop ebp
ret
Re:can't print string when passed on stack
While this makes sense in general, it comes into conflict with the gcc return mechanism for anything except a [tt]void[/tt] function. Under gcc, return values are passed through the EAX, EDX, and st(0) registers (according to the documentation on the DJGPP site, which should apply to any implementation of gcc for the x86 AFAIK).Pype.Clicker wrote: as a generic solution, encapsulate your ASM code within
Code: Select all
push ebp mov ebp,esp pushad ... asm code accesses arguments through [ebp+8], [ebp+12] ... popad pop ebp ret
Comments and corrections welcome.
Re:can't print string when passed on stack
What I usually do is:
This way I can still return values, but don't overwrite a value the calling function expects to stay the same...
Code: Select all
push ebp
mov ebp,esp
#push any used variables i want to save here
.......
#pop the variables here
pop ebp
ret