118334Speter! crt1.s for Solaris 2, x86 218334Speter 350397Sobrien! Copyright (C) 1993, 1998 Free Software Foundation, Inc. 418334Speter! Written By Fred Fish, Nov 1992 518334Speter! 618334Speter! This file is free software; you can redistribute it and/or modify it 718334Speter! under the terms of the GNU General Public License as published by the 818334Speter! Free Software Foundation; either version 2, or (at your option) any 918334Speter! later version. 1018334Speter! 1118334Speter! In addition to the permissions in the GNU General Public License, the 1218334Speter! Free Software Foundation gives you unlimited permission to link the 1318334Speter! compiled version of this file with other programs, and to distribute 1418334Speter! those programs without any restriction coming from the use of this 1518334Speter! file. (The General Public License restrictions do apply in other 1618334Speter! respects; for example, they cover modification of the file, and 1718334Speter! distribution when not linked into another program.) 1818334Speter! 1918334Speter! This file is distributed in the hope that it will be useful, but 2018334Speter! WITHOUT ANY WARRANTY; without even the implied warranty of 2118334Speter! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2218334Speter! General Public License for more details. 2318334Speter! 2418334Speter! You should have received a copy of the GNU General Public License 2518334Speter! along with this program; see the file COPYING. If not, write to 26169689Skan! the Free Software Foundation, 51 Franklin Street, Fifth Floor, 27169689Skan! Boston, MA 02110-1301, USA. 2818334Speter! 2918334Speter! As a special exception, if you link this library with files 3018334Speter! compiled with GCC to produce an executable, this does not cause 3118334Speter! the resulting executable to be covered by the GNU General Public License. 3218334Speter! This exception does not however invalidate any other reasons why 3318334Speter! the executable file might be covered by the GNU General Public License. 3418334Speter! 3518334Speter 3618334Speter! This file takes control of the process from the kernel, as specified 3718334Speter! in section 3 of the System V Application Binary Interface, Intel386 3818334Speter! Processor Supplement. It has been constructed from information obtained 3918334Speter! from the ABI, information obtained from single stepping existing 4018334Speter! Solaris executables through their startup code with gdb, and from 4118334Speter! information obtained by single stepping executables on other i386 SVR4 4218334Speter! implementations. This file is the first thing linked into any executable. 4318334Speter 4418334Speter .file "crt1.s" 4518334Speter .ident "GNU C crt1.s" 4618334Speter .weak _cleanup 4718334Speter .weak _DYNAMIC 4818334Speter .text 4918334Speter 5018334Speter! Start creating the initial frame by pushing a NULL value for the return 5118334Speter! address of the initial frame, and mark the end of the stack frame chain 5218334Speter! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. 5318334Speter! Initialize the first stack frame pointer in %ebp (the contents of which 5418334Speter! are unspecified at process initialization). 5518334Speter 5618334Speter .globl _start 5718334Speter_start: 5818334Speter pushl $0x0 5918334Speter pushl $0x0 6018334Speter movl %esp,%ebp 6118334Speter 6218334Speter! As specified per page 3-32 of the ABI, %edx contains a function 6318334Speter! pointer that should be registered with atexit(), for proper 6418334Speter! shared object termination. Just push it onto the stack for now 6518334Speter! to preserve it. We want to register _cleanup() first. 6618334Speter 6718334Speter pushl %edx 6818334Speter 6918334Speter! Check to see if there is an _cleanup() function linked in, and if 7018334Speter! so, register it with atexit() as the last thing to be run by 7118334Speter! atexit(). 7218334Speter 7318334Speter movl $_cleanup,%eax 7418334Speter testl %eax,%eax 7518334Speter je .L1 7618334Speter pushl $_cleanup 7718334Speter call atexit 7818334Speter addl $0x4,%esp 7918334Speter.L1: 8018334Speter 8118334Speter! Now check to see if we have an _DYNAMIC table, and if so then 8218334Speter! we need to register the function pointer previously in %edx, but 8318334Speter! now conveniently saved on the stack as the argument to pass to 8418334Speter! atexit(). 8518334Speter 8618334Speter movl $_DYNAMIC,%eax 8718334Speter testl %eax,%eax 8818334Speter je .L2 8918334Speter call atexit 9018334Speter.L2: 9118334Speter 9218334Speter! Register _fini() with atexit(). We will take care of calling _init() 9318334Speter! directly. 9418334Speter 9518334Speter pushl $_fini 9618334Speter call atexit 9718334Speter 9818334Speter! Compute the address of the environment vector on the stack and load 9918334Speter! it into the global variable _environ. Currently argc is at 8 off 10018334Speter! the frame pointer. Fetch the argument count into %eax, scale by the 10118334Speter! size of each arg (4 bytes) and compute the address of the environment 10218334Speter! vector which is 16 bytes (the two zero words we pushed, plus argc, 10318334Speter! plus the null word terminating the arg vector) further up the stack, 10418334Speter! off the frame pointer (whew!). 10518334Speter 10618334Speter movl 8(%ebp),%eax 10718334Speter leal 16(%ebp,%eax,4),%edx 10818334Speter movl %edx,_environ 10918334Speter 11018334Speter! Push the environment vector pointer, the argument vector pointer, 11118334Speter! and the argument count on to the stack to set up the arguments 11218334Speter! for _init(), _fpstart(), and main(). Note that the environment 11318334Speter! vector pointer and the arg count were previously loaded into 11418334Speter! %edx and %eax respectively. The only new value we need to compute 11518334Speter! is the argument vector pointer, which is at a fixed address off 11618334Speter! the initial frame pointer. 11718334Speter 11890075Sobrien! 11990075Sobrien! Make sure the stack is properly aligned. 12090075Sobrien! 12190075Sobrien andl $0xfffffff0,%esp 12290075Sobrien subl $4,%esp 12390075Sobrien 12418334Speter pushl %edx 12518334Speter leal 12(%ebp),%edx 12618334Speter pushl %edx 12718334Speter pushl %eax 12818334Speter 12918334Speter! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and 13018334Speter! main(argc, argv, environ). 13118334Speter 13218334Speter call _init 13318334Speter call __fpstart 13418334Speter call main 13518334Speter 13618334Speter! Pop the argc, argv, and environ arguments off the stack, push the 13718334Speter! value returned from main(), and call exit(). 13818334Speter 13918334Speter addl $12,%esp 14018334Speter pushl %eax 14118334Speter call exit 14218334Speter 14318334Speter! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. 14418334Speter 14518334Speter pushl $0x0 14618334Speter movl $0x1,%eax 14718334Speter lcall $7,$0 14818334Speter 14918334Speter! If all else fails, just try a halt! 15018334Speter 15118334Speter hlt 15218334Speter .type _start,@function 15318334Speter .size _start,.-_start 15418334Speter 15518334Speter! A dummy profiling support routine for non-profiling executables, 15618334Speter! in case we link in some objects that have been compiled for profiling. 15718334Speter 15850397Sobrien .weak _mcount 15918334Speter_mcount: 16018334Speter ret 16118334Speter .type _mcount,@function 16218334Speter .size _mcount,.-_mcount 163