Subversion Repositories SvarDOS

Rev

Rev 1558 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1558 Rev 1582
Line 1... Line 1...
1
; minimalist Watcom C startup routine - TINY memory model ONLY - (.COM files)
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
;
2
; kindly contributed by Bernd Boeckmann
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 :-)
3
 
34
 
4
.8086
35
.8086
5
 
36
 
-
 
37
IFNDEF STACKSIZE
6
STACK_SIZE = 2048
38
STACKSIZE = 400h
-
 
39
ENDIF
7
 
40
 
8
      DGROUP group _TEXT,_DATA,CONST,CONST2,_BSS,_EOF
41
      DGROUP group _TEXT,_DATA,CONST,CONST2,_BSS,_STACK
9
 
42
 
10
      extrn   "C",main : near
43
      extrn   "C",main : near
11
 
44
 
12
;      public _cstart_, _small_code_, __STK
-
 
13
      public _cstart_, _small_code_
45
      public _cstart_, _small_code_
14
 
46
 
15
_TEXT segment word public 'CODE'
47
_TEXT segment word public 'CODE'
16
      org   100h
48
      org   100h
17
 
49
 
18
_small_code_ label near
50
_small_code_ label near
19
 
51
 
20
_cstart_:
52
_cstart_ proc
21
 
-
 
22
      ; DOS puts the COM program in the largest memory block it can find
53
      ; DOS puts the COM program in the largest memory block it can find
23
      ; and sets SP to the end of this block. On top of that, it reserves
54
      ; and sets SP to the end of this block. On top of that, it reserves
24
      ; the entire memory (not only the process' block) to the program, which
55
      ; the entire memory (not only the process' block) to the program, which
25
      ; makes it impossible to allocate memory or run child processes.
56
      ; makes it impossible to allocate memory or run child processes.
26
      ; for this reasons it is beneficial to resize the memory block we occupy
57
      ; for this reasons it is beneficial to resize the memory block we occupy
27
      ; into a more reasonable value
58
      ; into a more reasonable value
28
 
59
 
29
      ; step 1: if SP > COM size + stack size, then set SP explicitely
60
    @verify_stack_size:
30
      ; POTENTIAL error: offset DGROUP:_EOF + STACK_SIZE may overflow!
61
      cmp sp,offset DGROUP:_stack_end_
31
      ; Has to be detected at linking stage, but WLINK does not catch it.
-
 
32
    adjustsp:
62
      ja @resize_mem
33
      cmp sp, offset DGROUP:_EOF + STACK_SIZE
63
      mov dx,offset @memerr
34
      jbe resizemem   ; JBE instead of JLE (unsigned comparison!)
64
      jmp _panic_
35
      mov sp, offset DGROUP:_EOF + STACK_SIZE
65
      @memerr db 'MEMERR$'
36
 
66
 
37
      ; step 2: resize our memory block to sp bytes (ie. sp/16 paragraphs)
67
      ; step 2: resize our memory block to sp bytes (ie. sp/16 paragraphs)
38
    resizemem:
68
    @resize_mem:
-
 
69
      mov sp,offset DGROUP:_stack_end_
-
 
70
      IFDEF STACKSTAT
-
 
71
        mov [_stack_low_],sp
-
 
72
      ENDIF STACKSTAT
39
      mov ah, 4ah
73
      mov ah,4ah
40
      mov bx, sp
74
      mov bx,sp
41
      shr bx, 1
75
      add bx,0fh
42
      shr bx, 1
76
      shr bx,1
43
      shr bx, 1
77
      shr bx,1
44
      shr bx, 1
78
      shr bx,1
45
      inc bx
79
      shr bx,1
46
      int 21h
80
      int 21h
47
 
81
 
48
      ; clear _BSS to be ANSI C conformant
82
      ; clear _BSS to be ANSI C conformant
49
      mov di, offset DGROUP:_BSS
83
      mov di,offset DGROUP:_BSS
50
      mov cx, offset DGROUP:_EOF
84
      mov cx,offset DGROUP:_STACK
51
      sub cx, di
85
      sub cx,di
-
 
86
      shr cx,1
52
      xor al, al
87
      xor ax,ax
53
      cld
88
      cld
54
      rep stosb
89
      rep stosw
-
 
90
 
-
 
91
      call main
-
 
92
      mov ah,4ch
-
 
93
      int 21h
-
 
94
_cstart_ endp
55
 
95
 
-
 
96
_panic_ proc
-
 
97
      ; output error message in DX, then terminate with FF
56
      call  main
98
      mov ah,9
57
      mov   ah, 4ch
99
      int 21h
-
 
100
      mov ax,4cffh      ; terminate if not enough stack space
58
      int   21h
101
      int 21h
-
 
102
_panic_ endp
-
 
103
 
-
 
104
      IFNDEF NOSTACKCHECK
59
 
105
 
-
 
106
public __STK
-
 
107
__STK proc
60
; Stack overflow checking routine is absent. Remember to compile your
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
61
; programs with the -s option to avoid referencing __STK
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$'
62
;__STK:
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:
63
;      ret
126
      ret
-
 
127
__STK endp
-
 
128
 
-
 
129
      ENDIF
64
 
130
 
65
_DATA segment word public 'DATA'
131
_DATA segment word public 'DATA'
66
_DATA ends
132
_DATA ends
67
 
133
 
68
CONST segment word public 'DATA'
134
CONST segment word public 'DATA'
Line 70... Line 136...
70
 
136
 
71
CONST2 segment word public 'DATA'
137
CONST2 segment word public 'DATA'
72
CONST2 ends
138
CONST2 ends
73
 
139
 
74
_BSS  segment word public 'BSS'
140
_BSS  segment word public 'BSS'
-
 
141
      IFDEF STACKSTAT
-
 
142
        public _stack_low_
-
 
143
        _stack_low_:  dw 1 dup(?)
-
 
144
      ENDIF STACKSTAT
75
_BSS  ends
145
_BSS  ends
76
 
146
 
77
; _EOF should be the last segment in .COM (see linker memory map)
147
; stack definition, available memory is checked at runtime
78
; if not, someone introduced other segments, or startup.obj is not the first
148
; defined as segment so that linker may detect .COM size overflow
-
 
149
_STACK segment para public 'TINY_STACK'
79
; linker object file
150
public _stack_end_
80
_EOF  segment word public
151
      db STACKSIZE dup(?)
-
 
152
_stack_end_:
81
_EOF  ends
153
_STACK ends
82
 
154
 
83
_TEXT ends
155
_TEXT ends
84
 
156
 
85
      end _cstart_
157
      end _cstart_
86
 
-