270 lines
6.1 KiB
NASM
270 lines
6.1 KiB
NASM
title c - C start up routine
|
|
|
|
;--------------------------------------------------------------------------
|
|
;
|
|
; Microsoft C Compiler Runtime for MS-DOS
|
|
;
|
|
; (C)Copyright Microsoft Corporation, 1984, 1985, 1986
|
|
;
|
|
;--------------------------------------------------------------------------
|
|
;
|
|
; How startup works in a few words -
|
|
;
|
|
; The startup and termination is performed by a few modules
|
|
;
|
|
; crt0.asm DOS 2.x/3.x specific init/term
|
|
; crt0msg.asm DOS 2.x/3.x error messages
|
|
; (winstart.asm) Windows specific init/term (not included)
|
|
;
|
|
; crt0dat.asm remainder of shared DOS 3.x init/term
|
|
;
|
|
; ************* IMPORTANT *****************************************
|
|
;
|
|
; If the user reassembles this module, he will need to link using the
|
|
; /DOSSEG switch or run the the DOSSEG.EXE program on crt0.obj, i.e.
|
|
;
|
|
; dosseg crt0.obj
|
|
;
|
|
; See the C documentation for more information about the /DOSSEG switch.
|
|
;
|
|
; All assembler modules must be assembled with the /mx switch, i.e.
|
|
;
|
|
; masm crt0/mx;
|
|
;
|
|
;--------------------------------------------------------------------------
|
|
|
|
|
|
?DF= 1 ; this is special for c startup
|
|
include version.inc
|
|
.xlist
|
|
include cmacros.inc
|
|
include msdos.inc
|
|
include brkctl.inc
|
|
.list
|
|
|
|
page
|
|
;===========================================================================
|
|
;
|
|
; Segment definitions
|
|
;
|
|
; The segment order is essentially the same as in XENIX.
|
|
; This module is edited after assembly to contain a dosseg comment
|
|
; record for the linker.
|
|
;
|
|
;===========================================================================
|
|
|
|
createSeg _TEXT, code, byte, public, CODE, <>
|
|
createSeg C_ETEXT,etext, byte, public, ENDCODE,<>
|
|
|
|
createSeg _DATA, data, word, public, DATA, DGROUP
|
|
createSeg STACK, stack, para, stack, STACK, DGROUP
|
|
|
|
defGrp DGROUP ; define DGROUP
|
|
|
|
codeOFFSET equ offset _TEXT:
|
|
dataOFFSET equ offset DGROUP:
|
|
|
|
page
|
|
|
|
public __acrtused ; trick to force in startup
|
|
__acrtused = 9876h ; funny value not easily matched in SYMDEB
|
|
|
|
extrn __acrtmsg:abs ; trick to pull in startup messages
|
|
|
|
|
|
sBegin stack
|
|
assumes ds,data
|
|
db 2048 dup (?) ; default stack size
|
|
sEnd
|
|
|
|
page
|
|
|
|
sBegin data
|
|
|
|
extrn _edata:byte ; end of data (start of bss)
|
|
extrn _end:byte ; end of bss (start of stack)
|
|
|
|
externW _psp ; psp:0 (paragraph #)
|
|
externW __argc
|
|
externDP __argv
|
|
externDP environ
|
|
|
|
; these are used by DOS C memory management (not used in Windows)
|
|
|
|
globalW _asizds,0 ; DS size (in bytes)
|
|
globalW _atopsp,0 ; top of stack (heap bottom)
|
|
|
|
labelW <PUBLIC,_abrktb> ; segment table for brkctl
|
|
dw ?
|
|
dw DGROUP
|
|
db (MAXSEG-1) * (size segrec) dup (?)
|
|
|
|
labelW <PUBLIC,_abrktbe>
|
|
globalW _abrkp,<dataoffset _abrktb>
|
|
|
|
sEnd
|
|
|
|
page
|
|
|
|
|
|
externP _cinit ; run-time initializers
|
|
|
|
externP _NMSG_TEXT ; pascal - find error message text
|
|
externP _NMSG_WRITE ; pascal - write error message to stdout
|
|
|
|
externP _setargv ; process command line arguments
|
|
externP _setenvp ; process environment
|
|
externP _nullcheck ; check for null assignment
|
|
|
|
externP main ; C main program
|
|
externP exit ; exit ( code )
|
|
|
|
if sizeC
|
|
extrn __exit:far ; _exit ( code) (cmacros name conflict)
|
|
else
|
|
extrn __exit:near
|
|
endif
|
|
|
|
|
|
sBegin code
|
|
assumes cs,code
|
|
assumes ds,nothing
|
|
|
|
labelNP <PUBLIC,_astart> ; start address of all "C" programs
|
|
|
|
; check MS-DOS version for 2.0 or later
|
|
|
|
callos VERSION
|
|
cmp al,2 ; check for version 2 or later
|
|
jae setup ; yes - continue with setup
|
|
|
|
mov ax,4
|
|
push ax
|
|
call _NMSG_TEXT ; find 'DOS 2.0 or later required'
|
|
xchg dx,ax
|
|
callos message
|
|
int 20h ; DOS 1.0 exit program
|
|
|
|
setup:
|
|
mov di,DGROUP
|
|
mov si,ds:[DOS_MAXPARA] ; get max. paragraph
|
|
sub si,di ; si = # para in data area
|
|
cmp si,1000h ; if more than 64K
|
|
jb setSP
|
|
|
|
mov si,1000H ; use full 64K (-16)
|
|
|
|
setSP:
|
|
cli ; turn off interrupts
|
|
mov ss,di ; SS = DGROUP
|
|
add sp,dataoffset _end-2 ; 2 for _asizds limit
|
|
sti ; turn interrupts back on
|
|
jnc SPok
|
|
|
|
xor ax,ax
|
|
push ax
|
|
call _NMSG_WRITE
|
|
mov ax,DOS_terminate shl 8 + 255
|
|
callos ; terminate process with 255
|
|
|
|
SPok:
|
|
assumes ss,data
|
|
|
|
and sp,not 1 ; make even (if not)
|
|
mov [_abrktb].sz,sp ; top DS free location
|
|
mov [_atopsp],sp ; save top of stack
|
|
|
|
mov ax,si ; si = # paragraphs
|
|
mov cl,4
|
|
shl ax,cl
|
|
dec ax
|
|
mov [_asizds],ax ; save DS size - 1 (in bytes)
|
|
|
|
; release extra space to DOS
|
|
|
|
add si,di ; si = DGROUP + # para in DGROUP
|
|
mov ds:[DOS_MAXPARA],si ; fix psp:2
|
|
mov bx,es ; bx = PSP base
|
|
sub bx,si ; bx = - # para used
|
|
neg bx
|
|
callos setmem ; set memory block size
|
|
mov [_psp],ds ; save psp:0
|
|
|
|
; zero data areas (_BSS and c_common)
|
|
|
|
push ss
|
|
pop es
|
|
assumes es,data
|
|
|
|
cld ; set direction flag (up)
|
|
mov di,dataOFFSET _edata ; beginning of bss area
|
|
mov cx,dataOFFSET _end ; end of bss area
|
|
sub cx,di
|
|
xor ax,ax
|
|
rep stosb ; zero bss
|
|
|
|
; C segmentation conventions set up here (DS=SS and CLD)
|
|
|
|
push ss ; set up initial DS=ES=SS, CLD
|
|
pop ds
|
|
assumes ds,data
|
|
|
|
; do necessary initialization BEFORE command line processing!
|
|
|
|
call _cinit ; shared by DOS and Windows
|
|
|
|
push ss
|
|
pop ds ; ds = DGROUP
|
|
assumes ds,data
|
|
|
|
; process command line and environment
|
|
|
|
call _setargv ; crack command line
|
|
call _setenvp ; crack environment
|
|
|
|
; call main and exit
|
|
|
|
xor bp,bp ; mark top stack frame for SYMDEB
|
|
|
|
if sizeD
|
|
push ds ; the environment is in DS
|
|
endif
|
|
push word ptr [environ]
|
|
|
|
if sizeD
|
|
push ds ; the arguments are in DS
|
|
endif
|
|
push word ptr [__argv]
|
|
|
|
push [__argc] ; move parameters onto stack
|
|
call main ; main ( argc , argv , envp )
|
|
|
|
; use whatever is in ax after returning here from the main program
|
|
|
|
push ax
|
|
call exit ; exit (AX)
|
|
; _exit will call terminators
|
|
|
|
page
|
|
;------------------------------------------------------------------------
|
|
;
|
|
; Fast exit fatal errors - die quick and return (255)
|
|
|
|
labelNP <PUBLIC,_cintDIV>
|
|
|
|
; _NMSG_WRITE will reestablish ds = DGROUP
|
|
|
|
mov ax,3 ; Integer divide by zero interrupt
|
|
|
|
labelNP <PUBLIC,_amsg_exit>
|
|
push ax
|
|
call _NMSG_WRITE ; write error message to stdout
|
|
|
|
mov ax,255
|
|
push ax
|
|
call __exit ; _exit(255)
|
|
|
|
|
|
sEnd
|
|
end _astart ; start address
|