]> 4ch.mooo.com Git - 16.git/blob - 16/lib/modex105/DEMOS/C/C_UTILS.ASM
wwww
[16.git] / 16 / lib / modex105 / DEMOS / C / C_UTILS.ASM
1 ;=======================================================\r
2 ;===  C_UTILS.ASM  - Asm Utilities for C/C++         ===\r
3 ;=======================================================\r
4 \r
5         PAGE    255, 132\r
6 \r
7         .MODEL Medium\r
8         .286\r
9 \r
10         ; ==== MACROS ====\r
11 \r
12         ; macros to PUSH and POP multiple registers\r
13 \r
14 PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
15         IFNB <R1>\r
16                 push    R1                              ; Save R1\r
17                 PUSHx   R2, R3, R4, R5, R6, R7, R8\r
18         ENDIF\r
19 ENDM\r
20 \r
21 POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
22         IFNB <R1>\r
23                 pop             R1                              ; Restore R1\r
24                 POPx    R2, R3, R4, R5, R6, R7, R8\r
25         ENDIF\r
26 ENDM\r
27 \r
28         ; Macro to Clear a Register to 0\r
29 \r
30 CLR MACRO Register\r
31         xor             Register, Register              ; Set Register = 0\r
32 ENDM\r
33 \r
34         ; Macros to Decrement Counter & Jump on Condition\r
35 \r
36 LOOPx MACRO Register, Destination\r
37         dec             Register                                ; Counter--\r
38         jnz             Destination                             ; Jump if not 0\r
39 ENDM\r
40 \r
41 LOOPjz MACRO Register, Destination\r
42         dec             Register                                ; Counter--\r
43         jz              Destination                             ; Jump if 0\r
44 ENDM\r
45 \r
46 \r
47         ; ==== General Constants ====\r
48 \r
49         False   EQU     0\r
50         True    EQU     -1\r
51         nil             EQU 0\r
52 \r
53         b               EQU     BYTE PTR\r
54         w               EQU     WORD PTR\r
55         d               EQU     DWORD PTR\r
56         o               EQU     OFFSET\r
57         f               EQU FAR PTR\r
58         s               EQU     SHORT\r
59         ?x4             EQU <?,?,?,?>\r
60         ?x3             EQU <?,?,?>\r
61 \r
62 \r
63         .Data\r
64 \r
65         EVEN\r
66 \r
67 RND_Seed        DW      7397, 29447, 802\r
68 RND_Mult        DW      179, 183, 182\r
69 RND_ModV        DW      32771, 32779, 32783\r
70 \r
71 CR_LF           DB      13, 10                  ; the CRLF data\r
72 \r
73         .Code\r
74 \r
75 ;===========================================\r
76 ;void far pascal dos_print  (far char *Text)\r
77 ;===========================================\r
78 ;\r
79 ; - Print Text Directly to DOS console w/ CR/LF\r
80 ;\r
81 \r
82         PUBLIC  DOS_PRINT\r
83 \r
84 DP_Stack        STRUC\r
85                                 DW      ?x4     ; DI, SI, DS, BP\r
86                                 DD      ?       ; Caller\r
87         DP_Text         DD      ?       ; Far Address of Text to print\r
88 DP_Stack        ENDS\r
89 \r
90 \r
91 DOS_PRINT        PROC    FAR\r
92                            \r
93         PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
94         mov             BP, SP                          ; Set up Stack Frame\r
95 \r
96         lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
97 \r
98         ; Compute Length of string\r
99 \r
100         CLR             CX                                      ; Length = 0\r
101         mov             SI, DX                          ; DS:SI = String data\r
102 \r
103 @@DP_Scan_it:\r
104         \r
105         cmp             b [SI], 0                       ; Null Byte found?\r
106         je              @@DP_Got_Len            ; exit loop if so\r
107 \r
108         inc             CX                                      ; Len++\r
109         inc             SI                                      ; Point to next char\r
110         jmp             s @@DP_Scan_it          ; check again...\r
111 \r
112 @@DP_Got_len:\r
113 \r
114         jcxz    @No_Print                       ; Don't Print if empty\r
115 \r
116         mov             BX, 1                           ; 1= DOS Handle for Display\r
117         mov             AH, 40h                         ; Write Text Function\r
118         int             21h                                     ; Call DOS to do it\r
119 \r
120 @No_Print:\r
121         mov             AX, SEG DGROUP          ; Restore DGroup\r
122         mov             DS, AX\r
123 \r
124         mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
125         mov             CX, 2                           ; 2 Characters to Write         \r
126         mov             BX, 1                           ; 1= DOS Handle for Display\r
127 \r
128         mov             AH, 40h                         ; Write Text Function\r
129         int             21h                                     ; Call DOS to do it\r
130 \r
131         cld                                                     ; Reset Direction Flag          \r
132         POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
133         ret             4                                       ; Exit & Clean Up Stack\r
134 \r
135 DOS_PRINT        ENDP\r
136 \r
137 \r
138 ;===========================================\r
139 ;void far pascal dos_prints (char far *Text)\r
140 ;===========================================\r
141\r
142 ; Print Text Directly to DOS console \r
143 ; without a trailing CR/LF\r
144 ;\r
145 \r
146         PUBLIC  DOS_PRINTS\r
147 \r
148 DOS_PRINTS       PROC    FAR\r
149 \r
150         PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
151         mov             BP, SP                          ; Set up Stack Frame\r
152 \r
153         lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
154 \r
155         ; Compute Length of string\r
156 \r
157         CLR             CX                                      ; Length = 0\r
158         mov             SI, DX                          ; DS:SI = String data\r
159 \r
160 @@DPS_Scan_it:\r
161         \r
162         cmp             b [SI], 0                       ; Null Byte found?\r
163         je              @@DPS_Got_Len           ; exit loop if so\r
164 \r
165         inc             CX                                      ; Len++\r
166         inc             SI                                      ; Point to next char\r
167         jmp             s @@DPS_Scan_it         ; check again...\r
168 \r
169 @@DPS_Got_len:\r
170 \r
171         jcxz    @DPS_Exit                       ; Don't Print if empty\r
172 \r
173         mov             BX, 1                           ; 1= DOS Handle for Display\r
174         mov             AH, 40h                         ; Write Text Function\r
175         int             21h                                     ; Call DOS to do it\r
176 \r
177 @DPS_Exit:\r
178         cld                                                     ; Reset Direction Flag          \r
179         POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
180         ret             2                                       ; Exit & Clean Up Stack\r
181 \r
182 DOS_PRINTS       ENDP\r
183 \r
184 \r
185 ;=========================================\r
186 ;void far pascal set_video_mode (int Mode)\r
187 ;=========================================\r
188 ;\r
189 ; Sets the Video Mode through the BIOS\r
190 ;\r
191 \r
192         PUBLIC  SET_VIDEO_MODE\r
193 \r
194 SVM_Stack       STRUC\r
195                                 DW      ?x4     ; DI, SI, DS, BP\r
196                                 DD      ?       ; Caller\r
197         SVM_Mode        DB      ?,? ; Desired Video Mode\r
198 SVM_Stack       ENDS\r
199 \r
200 \r
201 SET_VIDEO_MODE  PROC    FAR\r
202 \r
203         PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
204         mov             BP, SP                          ; Set up Stack Frame\r
205 \r
206         CLR             AH                                      ; Function 0\r
207         mov             AL, [BP].SVM_Mode       ; Get Mode #\r
208 \r
209         int             10H                                     ; Change Video Modes\r
210 \r
211 @SVM_Exit:\r
212         POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
213         ret             2                                       ; Exit & Clean Up Stack\r
214 \r
215 SET_VIDEO_MODE  ENDP\r
216 \r
217 \r
218 ;===================================\r
219 ;int far pascal scan_keyboard (void)\r
220 ;===================================\r
221 ;\r
222 ; Function to scan keyboard for a pressed key\r
223 ;\r
224 \r
225         PUBLIC  SCAN_KEYBOARD\r
226 \r
227 SCAN_KEYBOARD   PROC    FAR\r
228 \r
229         PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
230 \r
231         mov             AH, 01H                         ; Function #1\r
232         INT             16H                                     ; Call Keyboard Driver\r
233         JZ              @SK_NO_KEY                      ; Exit if Zero flag set\r
234 \r
235         mov             AH,     00H                             ; Remove Key from Buffer\r
236         INT             16H                                     ; Get Keycode in AX\r
237 \r
238         OR              AL, AL                          ; Low Byte Set (Ascii?)\r
239         JZ              @SK_Exit                        ; if not, it's a F-Key\r
240 \r
241         CLR             AH                                      ; Clear ScanCode if Ascii\r
242         JMP             s @SK_Exit                      ; Return Key in AX\r
243 \r
244 @SK_NO_KEY:\r
245         CLR             AX                                      ; Return Nil (no Keypress)\r
246 \r
247 @SK_Exit:\r
248         cld                                                     ; Reset Direction Flag          \r
249         POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
250         ret                                                     ; Exit & Clean Up Stack\r
251 \r
252 SCAN_KEYBOARD   ENDP\r
253 \r
254 \r
255 ;========================================\r
256 ;int far pascal random_int (int MaxValue)\r
257 ;========================================\r
258 ;\r
259 ; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
260 ;\r
261 \r
262 \r
263         PUBLIC  RANDOM_INT\r
264 \r
265 RI_Stack        STRUC\r
266                                 DW      ?       ; BP\r
267                                 DD      ?       ; Caller\r
268         RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
269 RI_Stack        ENDS\r
270 \r
271 \r
272 RANDOM_INT      PROC    FAR\r
273 \r
274         push    BP                                      ; Preserve Important Registers\r
275         mov             BP, SP                          ; Set up Stack Frame\r
276 \r
277         CLR             BX                                      ; BX is the data index\r
278         CLR             CX                              ; CX is the accumulator\r
279 \r
280 REPT 3\r
281         mov             AX, RND_Seed[BX]        ; load the initial seed\r
282         mul             RND_Mult[BX]            ; multiply it\r
283         div             RND_ModV[BX]            ; and obtain the Mod value\r
284         mov             RND_Seed[BX], DX        ; save that for the next time\r
285 \r
286         add             CX, DX                          ; add it into the accumulator\r
287         inc             BX\r
288         inc             BX                      ; point to the next set of values\r
289 ENDM\r
290 \r
291         mov             AX, CX                          ; AX = Random #\r
292         CLR             DX                                      ; DX = 0\r
293         div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
294 \r
295         mov             AX, DX\r
296 \r
297         pop             BP                                      ; Restore BP\r
298         ret             2                               ; back to BASIC with AX holding the result\r
299 \r
300 RANDOM_INT      ENDP\r
301 \r
302 \r
303 ;==================================\r
304 ;void far pascal init_random (void)\r
305 ;==================================\r
306 ;\r
307 ; Scrambles the psuedo-random number sequence\r
308 ; (XOR's the seed value with the timer)\r
309 ;\r
310 \r
311         PUBLIC  INIT_RANDOM\r
312 \r
313 INIT_RANDOM     PROC    FAR\r
314 \r
315         CLR             AX                                      ; Segment = 0000\r
316         mov             ES, AX\r
317         mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
318 \r
319         xor             RND_Seed, AX            ; Scramble 1st Seed\r
320 \r
321         ret                                                     ; Exit & Clean Up Stack\r
322 \r
323 INIT_RANDOM     ENDP\r
324 \r
325 ;=========================================\r
326 ;int far pascal int_sqr (int X, int Round)\r
327 ;=========================================\r
328 ;\r
329 ; Returns the Integer Square Root of (X)\r
330 ; Round allows the return value to be rounded to the \r
331 ; nearest integer value by passing 0x80.  Passing 0\r
332 ; return the Integer Portion only.  The rounding amound is\r
333 ; a number from 0 to 1 multiplied by 256, thus \r
334 ; 0.5 * 0x100 = 0x80!\r
335 ;\r
336 \r
337 ISQ_Stack       STRUC\r
338                                         DW      ?,?     ; BP, DI\r
339                                         DD      ?       ; Caller\r
340         ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
341         ISQ_X                   DW      ?       ; "X"\r
342 ISQ_Stack       ENDS\r
343 \r
344         PUBLIC  INT_SQR\r
345 \r
346 INT_SQR         PROC    FAR\r
347 \r
348     PUSHx   BP, DI                              ; Save BP\r
349     mov     BP, SP                              ; Set up Stack Frame\r
350 \r
351         xor     AX, AX                          ; {xor eax,eax}\r
352         xor     DX, DX                          ; {xor edx,edx}\r
353         mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
354 \r
355         mov     CX, 16                          ; {mov cx, 32}\r
356 \r
357 @ISQ_L:\r
358 \r
359         shl     DI, 1                           ; {shl edi,1}\r
360         rcl     DX, 1                           ; {rcl edx,1}\r
361         shl     DI, 1                           ; {shl edi,1}\r
362         rcl     DX, 1                           ; {rcl edx,1}\r
363         shl     AX, 1                           ; {shl eax,1}\r
364         mov     BX, AX                          ; {mov ebx,eax}\r
365         shl     BX, 1                           ; {shl ebx,1}\r
366         inc     BX                                      ; {inc ebx}\r
367         cmp     DX, BX                          ; {cmp edx,ebx}\r
368         jl              @ISQ_S\r
369 \r
370         sub     DX, BX                          ; {sub edx,ebx}\r
371         inc     AX                                      ; {inc eax}\r
372 \r
373 @ISQ_S: \r
374         loop    @ISQ_L\r
375 \r
376         add     ax, [BP].ISQ_Round      ; {add eax,$00008000}  \r
377                                                                 ; {*round* result in hi word: ie. +0.5}\r
378         shr     ax, 8                           ; {shr eax,16}  {to ax (result)}\r
379 \r
380         POPx    DI, BP                          ; Restore Registers     \r
381         ret             4                                       ; Exit\r
382 \r
383 INT_SQR         ENDP\r
384 \r
385 ;=================================\r
386 ;int far pascal timer_count (void)\r
387 ;=================================\r
388 ;\r
389 ; Returns the current timer value as an integer/long integer\r
390 ;\r
391 \r
392         PUBLIC  TIMER_COUNT\r
393 \r
394 TIMER_COUNT      PROC    FAR\r
395 \r
396         CLR             AX                                      ; Segment = 0000\r
397         mov             ES, AX\r
398         mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
399         mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
400         ret                                                     ; Exit & Clean Up Stack\r
401 \r
402 TIMER_COUNT      ENDP\r
403 \r
404 \r
405         END\r