On 24-Aug-01 Steve Roome wrote:
> Hi, I'm having some problems with (what ought to be) fairly
> straightforward assembly, mainly I think, with how FreeBSD (4.3, but
> does that matter ?) does function calls (which don't work for me!)
> 
> How exactly should functions work in assembly, afaict, the
> following C :
> 
> void printasint(int p) { printf ("print this %d\n", (int)p);}
> 
> should become :
> 
> printasint:
>       ## set up stack frame 
>       ## is this necessary, it was in the mailing lists ??
>       ##      popl %ebp
>       ##      mov %ebp, %edx
> 
>       ## okay, so these two lines shouldn't be necessary either
>       popl %eax
>       pushl %eax
>       ## as they don't do anything (do they, am I missing something??)
> 
>       pushl $.LC0
>       call printf
>       ## but where do I figure out where to "ret" to ??
>       ret
> .endofprintasint:
>               .size            printasint,.endofprintasint - printasint
> 
> Unfortunately, my code dies horribly, with illegal insruction, or
> somesuch, so I assume I'm returning to never never land, rather
> than where I was called from (but I'm not really sure how function
> calls are supposed to be handled, because the stuff that gcc -S
> comes out with is mad.. e.g. my functions start 
> 
> addl $12, %esp
> subl $-8, %esp
> 
> Which if I change to :
> 
> addl $12, %esp
> 
> causes a segfault.. (is that obvious, it doesn't seem to be ?)
> 
> Last time I did any large amount of assembly it was on the ARM, 10
> years ago, so please excuse my ignorance, I'm trying !!!

Heh.  Return addresses are saved on teh stack, so when your printasint() is
called, the call instruciton pushes %eip on the stack.  The 'ret' pops %eip off
the stack.  Now, in C, the calling function is responsible for cleaning up the
stack after calling a function (with respect to arguments).  (In some other
languages that don't support var args such as Pascal, the function fixes up
stack.)  All you are missing is the stack fixup.  To do that, you need to
adjust %esp to remove the values you pushed onto the stack as arguments.  Thus:

printasint:
        pushl %eax              # argument 1 (the int I assume)
        pushl $.LC0             # string
        call printf
        addl $8, %esp           # clean up stack
        ret

Your popl/pushl of %eax actually trashed the value in %eax with the return
address you were called from (unless that was hte point).  If that was the
point, then you could sort of cheat:

printmyretaddr:
        pushl $.LC0
        call printf
        addl $4,%esp            # just clean up the format string
        ret

HTH.

-- 

John Baldwin <[EMAIL PROTECTED]> -- http://www.FreeBSD.org/~jhb/
PGP Key: http://www.Baldwin.cx/~john/pgpkey.asc
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to