Subversion Repositories SvarDOS

Rev

Rev 1567 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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