Date: Fri, 24 Aug 2001 11:36:45 -0700 (PDT) From: John Baldwin <jhb@FreeBSD.org> To: "David O'Brien" <obrien@FreeBSD.org> Cc: freebsd-hackers@FreeBSD.org, Steve Roome <stephen_roome@yahoo.com> Subject: Re: function calls/rets in assembly Message-ID: <XFMail.010824113645.jhb@FreeBSD.org> In-Reply-To: <20010824110805.C88259@dragon.nuxi.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 24-Aug-01 David O'Brien wrote: > On Fri, Aug 24, 2001 at 01:01:39AM +0100, Steve Roome wrote: >> How exactly should functions work in assembly, afaict, the >> following C : >> >> void printasint(int p) { printf ("print this %d\n", (int)p);} > > Why not just ask the compiler?? > > $ cc -S -O0 printasint.c > $ cat printasint.s > > > .file "foo.c" > .version "01.01" > gcc2_compiled.: > .section .rodata > .LC0: > .byte 0x70,0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x69,0x73 > .byte 0x20,0x25,0x64,0xa,0x0 > .text > .p2align 2,0x90 > .globl printasint > .type printasint,@function > printasint: > pushl %ebp > movl %esp,%ebp > subl $8,%esp > addl $-8,%esp > movl 8(%ebp),%eax > pushl %eax > pushl $.LC0 > call printf > addl $16,%esp > .L2: > leave > ret > .Lfe1: Because this code is broken and obfuscated? :) We save %esp in %ebp (the only thing that keeps it from breaking) then for some reason allocate two quadwords on the stack unnecessarily, one using an add instruction, one using a sub. Then we push the two dword args on the stack and call the function. After the call, we adjust the stack by 16, even though we only used 8 bytes of arguments! Thus, it seems to be reclaiming one of the 2 quadwords it allocated on the stack in addition to the arguments passed to the function. At this point if we did a 'pop %ebp' instead of leave, things would break since we have a misaligned stack, but the leave restores the %esp from %ebp, before pop'ing %ebp thus working around the bogus stack handling. A better version would be this: printasint: pushl %ebp movl %ebp, %esp pushl 8(%ebp) pushl $.LC0 call printf addl $8,%esp leave ret Note that with hand optimizing, you could axe the addl after the call since leave will clean up after that anyways. Also, you don't really need a frame here anyways. In that case, you could just push 8(%esp) as your first instruction and axe the leave (but leave the addl). -- 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.010824113645.jhb>