sol2-c1.asm revision 169690
1169691Skan! crt1.s for Solaris 2, x86 2169691Skan 3169691Skan! Copyright (C) 1993, 1998 Free Software Foundation, Inc. 4169691Skan! Written By Fred Fish, Nov 1992 5169691Skan! 6169691Skan! This file is free software; you can redistribute it and/or modify it 7169691Skan! under the terms of the GNU General Public License as published by the 8169691Skan! Free Software Foundation; either version 2, or (at your option) any 9169691Skan! later version. 10169691Skan! 11169691Skan! In addition to the permissions in the GNU General Public License, the 12169691Skan! Free Software Foundation gives you unlimited permission to link the 13169691Skan! compiled version of this file with other programs, and to distribute 14169691Skan! those programs without any restriction coming from the use of this 15169691Skan! file. (The General Public License restrictions do apply in other 16169691Skan! respects; for example, they cover modification of the file, and 17169691Skan! distribution when not linked into another program.) 18169691Skan! 19169691Skan! This file is distributed in the hope that it will be useful, but 20169691Skan! WITHOUT ANY WARRANTY; without even the implied warranty of 21169691Skan! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22169691Skan! General Public License for more details. 23169691Skan! 24169691Skan! You should have received a copy of the GNU General Public License 25169691Skan! along with this program; see the file COPYING. If not, write to 26169691Skan! the Free Software Foundation, 51 Franklin Street, Fifth Floor, 27169691Skan! Boston, MA 02110-1301, USA. 28169691Skan! 29169691Skan! As a special exception, if you link this library with files 30169691Skan! compiled with GCC to produce an executable, this does not cause 31169691Skan! the resulting executable to be covered by the GNU General Public License. 32169691Skan! This exception does not however invalidate any other reasons why 33169691Skan! the executable file might be covered by the GNU General Public License. 34169691Skan! 35169691Skan 36169691Skan! This file takes control of the process from the kernel, as specified 37169691Skan! in section 3 of the System V Application Binary Interface, Intel386 38169691Skan! Processor Supplement. It has been constructed from information obtained 39169691Skan! from the ABI, information obtained from single stepping existing 40169691Skan! Solaris executables through their startup code with gdb, and from 41169691Skan! information obtained by single stepping executables on other i386 SVR4 42169691Skan! implementations. This file is the first thing linked into any executable. 43169691Skan 44169691Skan .file "crt1.s" 45169691Skan .ident "GNU C crt1.s" 46169691Skan .weak _cleanup 47169691Skan .weak _DYNAMIC 48169691Skan .text 49169691Skan 50169691Skan! Start creating the initial frame by pushing a NULL value for the return 51169691Skan! address of the initial frame, and mark the end of the stack frame chain 52169691Skan! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. 53169691Skan! Initialize the first stack frame pointer in %ebp (the contents of which 54169691Skan! are unspecified at process initialization). 55169691Skan 56169691Skan .globl _start 57169691Skan_start: 58169691Skan pushl $0x0 59169691Skan pushl $0x0 60169691Skan movl %esp,%ebp 61169691Skan 62169691Skan! As specified per page 3-32 of the ABI, %edx contains a function 63169691Skan! pointer that should be registered with atexit(), for proper 64169691Skan! shared object termination. Just push it onto the stack for now 65169691Skan! to preserve it. We want to register _cleanup() first. 66169691Skan 67169691Skan pushl %edx 68169691Skan 69169691Skan! Check to see if there is an _cleanup() function linked in, and if 70169691Skan! so, register it with atexit() as the last thing to be run by 71169691Skan! atexit(). 72169691Skan 73169691Skan movl $_cleanup,%eax 74169691Skan testl %eax,%eax 75169691Skan je .L1 76169691Skan pushl $_cleanup 77169691Skan call atexit 78169691Skan addl $0x4,%esp 79169691Skan.L1: 80169691Skan 81169691Skan! Now check to see if we have an _DYNAMIC table, and if so then 82169691Skan! we need to register the function pointer previously in %edx, but 83169691Skan! now conveniently saved on the stack as the argument to pass to 84169691Skan! atexit(). 85169691Skan 86169691Skan movl $_DYNAMIC,%eax 87169691Skan testl %eax,%eax 88169691Skan je .L2 89169691Skan call atexit 90169691Skan.L2: 91169691Skan 92169691Skan! Register _fini() with atexit(). We will take care of calling _init() 93169691Skan! directly. 94169691Skan 95169691Skan pushl $_fini 96169691Skan call atexit 97169691Skan 98169691Skan! Compute the address of the environment vector on the stack and load 99169691Skan! it into the global variable _environ. Currently argc is at 8 off 100169691Skan! the frame pointer. Fetch the argument count into %eax, scale by the 101169691Skan! size of each arg (4 bytes) and compute the address of the environment 102169691Skan! vector which is 16 bytes (the two zero words we pushed, plus argc, 103169691Skan! plus the null word terminating the arg vector) further up the stack, 104169691Skan! off the frame pointer (whew!). 105169691Skan 106169691Skan movl 8(%ebp),%eax 107169691Skan leal 16(%ebp,%eax,4),%edx 108169691Skan movl %edx,_environ 109169691Skan 110169691Skan! Push the environment vector pointer, the argument vector pointer, 111169691Skan! and the argument count on to the stack to set up the arguments 112169691Skan! for _init(), _fpstart(), and main(). Note that the environment 113169691Skan! vector pointer and the arg count were previously loaded into 114169691Skan! %edx and %eax respectively. The only new value we need to compute 115169691Skan! is the argument vector pointer, which is at a fixed address off 116169691Skan! the initial frame pointer. 117169691Skan 118169691Skan! 119! Make sure the stack is properly aligned. 120! 121 andl $0xfffffff0,%esp 122 subl $4,%esp 123 124 pushl %edx 125 leal 12(%ebp),%edx 126 pushl %edx 127 pushl %eax 128 129! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and 130! main(argc, argv, environ). 131 132 call _init 133 call __fpstart 134 call main 135 136! Pop the argc, argv, and environ arguments off the stack, push the 137! value returned from main(), and call exit(). 138 139 addl $12,%esp 140 pushl %eax 141 call exit 142 143! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. 144 145 pushl $0x0 146 movl $0x1,%eax 147 lcall $7,$0 148 149! If all else fails, just try a halt! 150 151 hlt 152 .type _start,@function 153 .size _start,.-_start 154 155! A dummy profiling support routine for non-profiling executables, 156! in case we link in some objects that have been compiled for profiling. 157 158 .weak _mcount 159_mcount: 160 ret 161 .type _mcount,@function 162 .size _mcount,.-_mcount 163