Subversion Repositories SvarDOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2244 mateusz.vi 1
; WMINICRT - minimal runtime for (Open) Watcom C to generate DOS .COM files
2
;
3
; The default behaviour of the runtime is:
4
;   - sets up a stack of 400H bytes
5
;   - releases additional memory beyond stack to DOS
6
;   - panics on initialization, if not enough memory for stack size
7
;   - panics if running out of stack during execution
8
;
9
; WASM definitions:
10
;   STACKSIZE=<value>     define stack size other than 400h
11
;   NOSTACKCHECK          do not assemble __STK function
12
;   STACKSTAT             remember the minimum SP, maintained by __STK__
13
;                         and exported via _stack_low_.
14
;
15
; To build an executable without build- and linker scripts run:
16
;   wasm startup.asm
17
;   wcc -0 -bt=dos -ms -os -zl your_c_file.c
18
;   wlink system dos com file startup,your_c_file
19
; To change the stack size, add -DSTACKSIZE=<value> to the wasm call
20
;
21
; To compile without stack checking:
22
;   a) compile this startup file with wasm -DNOSTACKCHECK startup.asm
23
;   b) call the C compiler with -s flag
24
;
25
; To build a debug version of your program:
26
;   wasm -d1 startup.asm
27
;   wcc -bt=dos -ms -d2 -zl your_c_file.c
28
;   wlink system dos com debug all option map file startup,your_c_file
29
;
30
; TODO:
31
;   - display stack statistics on program termination if STACKSTAT is enabled
32
;   - proper Makefiles
33
;   - many more (optional) things while keeping it small :-)
34
 
35
.8086
36
 
37
IFNDEF STACKSIZE
38
STACKSIZE = 400h
39
ENDIF
40
 
41
      DGROUP group _TEXT,_DATA,CONST,CONST2,_BSS,_STACK
42
 
43
      extrn   "C",main : near
44
 
45
      public _cstart_, _small_code_
46
 
47
_TEXT segment word public 'CODE'
48
      org   100h
49
 
50
_small_code_ label near
51
 
52
_cstart_ proc
53
      ; DOS puts the COM program in the largest memory block it can find
54
      ; and sets SP to the end of this block. On top of that, it reserves
55
      ; the entire memory (not only the process' block) to the program, which
56
      ; makes it impossible to allocate memory or run child processes.
57
      ; for this reasons it is beneficial to resize the memory block we occupy
58
      ; into a more reasonable value
59
 
60
    @verify_stack_size:
61
      cmp sp,offset DGROUP:_stack_end_
62
      ja @resize_mem
63
      mov dx,offset @memerr
64
      jmp _panic_
65
      @memerr db 'MEMERR$'
66
 
67
      ; step 2: resize our memory block to sp bytes (ie. sp/16 paragraphs)
68
    @resize_mem:
69
      mov sp,offset DGROUP:_stack_end_
70
      IFDEF STACKSTAT
71
        mov [_stack_low_],sp
72
      ENDIF STACKSTAT
73
      mov ah,4ah
74
      mov bx,sp
75
      add bx,0fh
76
      shr bx,1
77
      shr bx,1
78
      shr bx,1
79
      shr bx,1
80
      int 21h
81
 
82
      ; clear _BSS to be ANSI C conformant
83
      mov di,offset DGROUP:_BSS
84
      mov cx,offset DGROUP:_STACK
85
      sub cx,di
86
      shr cx,1
87
      xor ax,ax
88
      cld
89
      rep stosw
90
 
91
      call main
92
      mov ah,4ch
93
      int 21h
94
_cstart_ endp
95
 
96
_panic_ proc
97
      ; output error message in DX, then terminate with FF
98
      mov ah,9
99
      int 21h
100
      mov ax,4cffh      ; terminate if not enough stack space
101
      int 21h
102
_panic_ endp
103
 
104
      IFNDEF NOSTACKCHECK
105
 
106
public __STK
107
__STK proc
108
      ; ensures that we have enough stack space left. the needed bytes are
109
      ; given in AX. panics if stack low.
110
      sub ax,sp         ; subtract needed bytes from SP
111
      neg ax            ; SP-AX = -(AX-SP)
112
      cmp ax,offset DGROUP:_STACK - 2 ; -2 is to compensate for __STK ret addr
113
      jae @l1           ; enough stack => return, else panic
114
      int 3             ; trap into debugger
115
      mov dx,offset @stkerr
116
      add sp,200h       ; make sure we have enough stack to call DOS
117
      jmp _panic_
118
      @stkerr db 'STKERR$'
119
@l1:
120
      IFDEF STACKSTAT   ; update lowest stack pointer if statistics enabled
121
        cmp [_stack_low_],ax
122
        jbe @r
123
        mov [_stack_low_],ax
124
      ENDIF STACKSTAT
125
@r:
126
      ret
127
__STK endp
128
 
129
      ENDIF
130
 
131
_DATA segment word public 'DATA'
132
_DATA ends
133
 
134
CONST segment word public 'DATA'
135
CONST ends
136
 
137
CONST2 segment word public 'DATA'
138
CONST2 ends
139
 
140
_BSS  segment word public 'BSS'
141
      IFDEF STACKSTAT
142
        public _stack_low_
143
        _stack_low_:  dw 1 dup(?)
144
      ENDIF STACKSTAT
145
_BSS  ends
146
 
147
; stack definition, available memory is checked at runtime
148
; defined as segment so that linker may detect .COM size overflow
149
_STACK segment para public 'TINY_STACK'
150
public _stack_end_
151
      db STACKSIZE dup(?)
152
_stack_end_:
153
_STACK ends
154
 
155
_TEXT ends
156
 
157
      end _cstart_