Date: Thu, 23 Aug 2001 17:24:22 -0700 (PDT) From: John Baldwin <jhb@freebsd.org> To: Steve Roome <stephen_roome@yahoo.com> Cc: freebsd-hackers@freebsd.org Subject: RE: function calls/rets in assembly Message-ID: <XFMail.010823172422.jhb@FreeBSD.org> In-Reply-To: <20010824010139.E365@dylan.home>
next in thread | previous in thread | raw e-mail | index | archive | help
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 <jhb@FreeBSD.org> -- 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 majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.010823172422.jhb>