summaryrefslogtreecommitdiff
path: root/v4.0/src/MAPPER/GETMSG.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/MAPPER/GETMSG.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/MAPPER/GETMSG.ASM')
-rw-r--r--v4.0/src/MAPPER/GETMSG.ASM586
1 files changed, 586 insertions, 0 deletions
diff --git a/v4.0/src/MAPPER/GETMSG.ASM b/v4.0/src/MAPPER/GETMSG.ASM
new file mode 100644
index 0000000..12dfaa3
--- /dev/null
+++ b/v4.0/src/MAPPER/GETMSG.ASM
@@ -0,0 +1,586 @@
1;
2page 80,132
3;
4title CP/DOS DosGetMessage mapper
5;
6messages segment word public 'messages'
7
8OurMessage db 0dh,0ah,"DosGetMessage returning ->",'$'
9
10ErrorMessageFlag db 0
11MessageToGo dw 0
12MessageLength dw 0
13NextVarPointer dd 0
14VarsToGo dw 0
15
16MaxMessageNumber = 0
17
18; This macro is used to define/declare all of the messages
19
20; We will have four macros, msg -> defines a complete message
21; msgStart -> defines the first part of a message
22; msgContinue -> continues a started message
23; msgEnd -> ends a message
24
25MacroState = 0
26
27;----------------------------------------------
28
29MsgError macro text ; message string error
30
31 if1
32 else
33 %out 
34 %out $ERROR - &text
35 endif
36
37 $ERROR - &text
38
39 endm
40
41;----------------------------------------------
42
43msg macro number,text
44
45 if MacroState NE 0
46 MsgError <Cannot use the 'Msg' Macro when inside a message definition.>
47 mexit
48 endif
49
50Message&Number db text
51 db 0
52
53 if MaxMessageNumber lt &number
54 MaxMessageNumber = &Number
55 endif
56
57MacroState = 0
58
59 endm
60
61;----------------------------------------------
62
63msgStart macro number,text ; start of a message string
64
65 if MacroState NE 0
66 MsgError <Cannot use the 'MsgStart' macro when inside a message definition.>
67 mexit
68 endif
69
70Message&Number db text
71
72 if MaxMessageNumber lt &number
73 MaxMessageNumber = &Number
74 endif
75
76MacroState = 1
77
78 endm
79
80;----------------------------------------------
81
82msgContinue macro text ; messgage string contination
83
84 if MacroState EQ 0
85 MsgError <Cannot use the 'MsgContinue' macro unless inside a message definition.>
86 mexit
87 endif
88
89 db text
90
91MacroState = 1
92
93 endm
94
95;----------------------------------------------
96
97msgEnd macro ; end of message string
98
99 if MacroState EQ 0
100 MsgError <Cannot use the 'MsgEnd' macro unless inside a message definition.>
101 mexit
102 endif
103
104 db 0
105
106MacroState = 0
107
108 endm
109
110
111;-----------------------------------------------
112
113; Define/declare the messages first!
114
115 include messages.inc
116
117NotFoundNumber = -2
118
119NotFoundMessage label byte
120 msg NotFoundNumber,<'We could not find your message #'>
121
122; Now, for each defined message, generate an index
123
124msgidx macro number
125 ifdef Message&Number
126 dw &Number
127 dw offset messages:Message&Number
128 endif
129 endm
130
131 even
132
133MessageIndex label word
134
135ThisMessageNumber = 0
136 rept MaxMessageNumber + 1
137 msgidx %ThisMessageNumber
138ThisMessageNumber = ThisMessageNumber + 1
139 endm
140
141 dw -1
142
143NotFoundIndex dw -2
144 dw offset messages:NotFoundMessage
145
146messages ends
147;
148dosxxx segment byte public 'dos'
149 assume cs:dosxxx,ds:nothing,es:nothing,ss:nothing
150;
151;**********************************************************************
152;*
153;* MODULE: dosgetmessage
154;*
155;* FILE NAME: dos029.asm
156;*
157;* CALLING SEQUENCE:
158;*
159;* push@ other insert variable table
160;* push word insert variable count
161;* push@ other message buffer address
162;* push word buffer length
163;* push word message number
164;* push@ asciiz message file name
165;* push@ word returned message length
166;* call dosgetmessage
167;*
168;* MODULES CALLED: None (preliminary version)
169;*
170;*********************************************************************
171;
172 public dosgetmessage
173 .sall
174 .xlist
175 include macros.inc
176 .list
177
178str struc
179old_bp dw ?
180return dd ?
181ReturnLengthPtr dd ? ; length of returned message
182MessageFileName dd ? ; message file name
183MessageNumber dw ? ; number of the message
184MessageBufferLen dw ? ; length of the message buffer
185MessageBufferPtr dd ? ; buffer address to return message
186VariablesCount dw ? ; number of variables
187VariableTablePtr dd ? ; table of variables to insert
188str ends
189
190
191dosgetmessage proc far
192
193 Enter Dosgetmessage ; push registers
194 mov ax,messages ; setup message buffer
195 mov ds,ax
196 assume ds:messages
197 mov ErrorMessageFlag,0 ; reset error message flag
198
199 mov bx,[bp].MessageNumber ; get message number
200 mov si,offset messages:MessageIndex
201
202SearchForMessageLoop: ; search for message in table
203 lodsw
204 cmp ax,bx ; found ??
205 je FoundMessage ; jump if true
206
207 add si,2 ; if not serach continues
208 cmp ax,-1
209 jne SearchForMessageLoop
210
211 mov si,offset messages:NotFoundIndex + 2
212 mov ErrorMessageFlag,1
213
214; Here, ds:[si] -> word message number, followed by word message offset
215
216FoundMessage:
217 mov si,ds:[si]
218
219; Here, ds:[si] -> message text bytes
220
221 les di,[bp].VariableTablePtr ; get variable address
222 mov word ptr NextVarPointer+0,di ; save it
223 mov word ptr NextVarPointer+2,es
224
225 mov di,[bp].VariablesCount ; get variable count
226 mov VarsToGo,di ; save it
227
228 les di,[bp].MessageBufferPtr ; get return message buffer
229 ; address
230 mov ax,[bp].MessageBufferLen ; get return message buffer
231 mov MessageToGo,ax ; length
232
233 cmp ax,0 ; length = 0 ??
234 jne HaveLengthToCopy ; if not, jump
235
236 jmp GetMessageDone ; done
237
238HaveLengthToCopy:
239 mov MessageLength,0 ; initialize counter
240
241MoveCharsLoop:
242 lodsb ; get next character
243 cmp al,'%' ; is it a % sign
244 je DoSubstitution ; if so, need substitution
245
246 cmp al,0 ; end of string ??
247 jne RealCharacter ; if not look for real chars
248
249 jmp GetMessageDone ; else, jump to update
250 ; return message length
251
252RealCharacter: ; look for real character
253 stosb
254 inc MessageLength ; update message length counter
255 dec MessageToGo
256 jnz MoveCharsLoop ; branch if not all done
257
258 jmp GetMessageDone ; else alldone, branch
259
260DoSubstitution: ; do substitution
261 lodsb ; get character
262 cmp al,'%' ; check for %%
263 je RealCharacter ; if so, get next character
264
265
266
267; skip the numbers that indicate field width!
268
269SkipFieldWidth: ; check for field width digit
270 cmp al,'0' ; indicator digits
271 jc CheckChar
272
273 cmp al,'9'+1
274 jnc CheckChar
275 ; if field width indicator
276 lodsb ; jump to examine next char
277 jmp SkipFieldWidth
278
279;-----------------------------------------
280
281CheckChar: ; check for char substitution
282 cmp al,'c' ; if true go do character
283 je SubstituteChar ; substitution
284 cmp al,'C'
285 jne CheckDecimal
286
287SubstituteChar: ; do character subtitution
288 push ds
289 push si
290 lds si,NextVarPointer
291 lds si,ds:dword ptr [si]
292
293 assume ds:nothing
294
295 lodsb
296 pop si
297 pop ds
298
299 assume ds:messages
300
301 add word ptr NextVarPointer,4
302 dec VarsToGo
303
304 jmp RealCharacter
305
306;-----------------------------------------
307
308CheckDecimal: ; check for decimal subtitution
309 cmp al,'d' ; if true, do decimal
310 je SubstituteDecimal ; substitution
311 cmp al,'D'
312 jne CheckString
313
314SubstituteDecimal: ; do decimal subtitution
315 push ds
316 push si
317 lds si,NextVarPointer
318 lds si,ds:dword ptr [si]
319
320 assume ds:nothing
321
322 lodsw
323 pop si
324 pop ds
325
326 assume ds:messages
327
328 add word ptr NextVarPointer,4
329 dec VarsToGo
330
331 mov dx,0
332 call ConvDec
333
334 add MessageLength,ax
335 sub MessageToGo,ax
336 jc PastEndOfBuffer
337
338 jmp MoveCharsLoop
339
340PastEndOfBuffer:
341 jmp GetMessageDone
342
343;-----------------------------------------
344
345CheckString:
346 cmp al,'s' ; check for string subtitution
347 je SubstituteString ; if true, do string
348 cmp al,'S' ; substitution
349 jne CheckLong
350
351SubstituteString: ; do string substitution
352 push ds
353 push si
354 mov cx,MessageToGo
355 mov dx,MessageLength
356 lds si,NextVarPointer
357 lds si,ds:dword ptr [si]
358 assume ds:nothing
359
360ContinueStringSubstitution:
361 lodsb
362 cmp al,0
363 je EndOfSubstituteString
364
365 stosb
366 inc dx
367 loop ContinueStringSubstitution
368
369EndOfSubstituteString:
370 pop si
371 pop ds
372 assume ds:messages
373
374 add word ptr NextVarPointer,4
375 dec VarsToGo
376
377 mov MessageLength,dx
378 mov MessageToGo,cx
379 jcxz PastEndOfBuffer
380
381 jmp MoveCharsLoop
382
383;-----------------------------------------
384
385CheckLong: ; need long substitution
386 cmp al,'l'
387 je SubstituteLong ; if true go do it
388 cmp al,'L'
389 jne Unknown ; else unknown substitution
390
391SubstituteLong:
392 jmp RealCharacter ; just go back
393
394;-----------------------------------------
395
396Unknown:
397 jmp RealCharacter ; just go back
398
399
400
401
402; Update the return message length
403
404GetMessageDone:
405 push ds
406 push si
407 mov ax,MessageLength
408 lds si,[bp].ReturnLengthPtr
409 assume ds:nothing
410 mov ds:[si],ax
411 pop si
412 pop ds
413 assume ds:messages
414
415 cmp ErrorMessageFlag,0
416 je NotErrorMessage
417
418 mov ErrorMessageFlag,0
419
420KeepGoingBackwards:
421 cmp es:byte ptr [di-1],0
422 jne PutItHere
423
424 dec di
425 jmp KeepGoingBackwards
426
427PutItHere:
428 mov ax,[bp].MessageNumber
429 mov dx,0
430
431 call convdec
432 lds si,[bp].ReturnLengthPtr
433 assume ds:nothing
434 add ax,3 ; for cr, lf, nul
435 add ds:[si],ax
436
437 mov al,0dh
438 stosb
439 mov al,0ah
440 stosb
441
442 mov al,0
443 stosb
444
445NotErrorMessage:
446 jmp SkipToHere
447
448 mov dx,seg messages
449 mov ds,dx
450 mov dx,offset messages:OurMessage
451
452 mov ah,9 ; load op code
453 int 21h ; display message
454
455 lds si,[bp].ReturnLengthPtr
456 mov cx,ds:[si]
457 lds dx,[bp].MessageBufferPtr
458
459 mov bx,1
460 mov ah,40h
461 int 21h ; display message
462
463SkipToHere:
464 xor ax,ax ; set good return code
465
466 mexit ; pop registers
467 ret size str - 6 ; return
468
469dosgetmessage endp
470
471 page
472
473;������������������������������������������������������������������
474
475Tens dd 10000000
476 dd 1000000
477 dd 100000
478 dd 10000
479 dd 1000
480 dd 100
481 dd 10
482 dd 1
483 dd 0
484
485convdec proc near
486
487; input es:di -> location to put decimal characters at
488; dx:ax -> 32bit value to be displayed
489
490; output es:di -> next location for output characters
491; ax = number of characters output
492
493 push bp
494 sub sp,6
495 mov bp,sp
496
497DecLength equ word ptr [bp+0]
498LowValue equ word ptr [bp+2]
499HighValue equ word ptr [bp+4]
500
501 mov DecLength,0
502 mov HighValue,dx
503 mov LowValue,ax
504
505 mov bx,offset dosxxx:Tens
506
507; Start with a count of zero.
508
509DigitLoop:
510 mov dx,0
511
512; Loop, counting the number of times you can subtract the current digit value
513
514CountLoop:
515 mov ax,cs:[bx+0]
516 sub LowValue,ax
517 mov ax,cs:[bx+2]
518 sbb HighValue,ax
519 jc TooFar
520 inc dx ; Subtraction did no go negative, inc digit
521 jmp CountLoop
522
523; Since we know when this digit is done by the number going negative, we must
524; fixup the damage.
525
526TooFar:
527 mov ax,cs:[bx+0]
528 add LowValue,ax
529 mov ax,cs:[bx+2]
530 adc HighValue,ax
531
532; We need to supress leading zeros, so check to see if this digit is non zero
533
534 cmp dx,0
535 jnz DoDisplay
536
537; Digit is zero, check to see if we have put out any digits yet?
538
539 cmp Declength,0
540 jz NextDigit
541
542; Either digit was non zero, or we have already output the leading non-zero.
543; It really doesn't matter, display the digit
544
545DoDisplay:
546 mov al,dl
547 add al,'0'
548 stosb
549 inc DecLength
550
551; Set up for the next digit, and determine if we are done
552
553NextDigit:
554 add bx,4
555 cmp cs:word ptr [bx+0],0
556 jnz DigitLoop
557 cmp cs:word ptr [bx+2],0
558 jnz DigitLoop
559
560; Check to see that we at least put out a single 0 character
561
562 cmp DecLength,0
563 jne Done
564
565; We didn't, so let's put the zero there
566
567 mov al,'0'
568 stosb
569 inc DecLength
570
571; The decimal display is complete. Get the return value and return
572
573Done:
574 mov ax,DecLength
575
576 mov sp,bp
577 add sp,6
578 pop bp
579
580 ret
581
582convdec endp
583
584dosxxx ends
585
586 end