1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
page ,132 ;
TITLE RECPROC.SAL
;*****************************************************************************
; Include files
;*****************************************************************************
.xlist
include recseg.inc ;AN000;bgb
include dossym.inc ;AN000;bgb
INCLUDE SYSCALL.INC ;AN000;bgb
INCLUDE RECMACRO.INC ;AN000;bgb
include recequ.inc ;AN000;bgb
include pathmac.inc
.xcref
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
.cref
;
;*****************************************************************************
; Extrn Declarations
;*****************************************************************************
data segment PUBLIC para 'DATA' ;AC000;bgb
EXTRN secs_per_64k:word
EXTRN paras_per_fat:word
EXTRN paras_per_64k:word
EXTRN bytes_per_sector:word
EXTRN sec_count:word
EXTRN OFMSG_PTR:WORD
EXTRN y_value_lo:WORD ;AN000;bgb
EXTRN y_value_hi:WORD ;AN000;bgb ; AC000;SM
EXTRN x_value_lo:WORD ;AN000;bgb ; AC000;SM
EXTRN x_value_hi:WORD ;AN000;bgb ; AC000;SM
EXTRN dbcs_vector:byte ;AN000;bgb ; AC000;SM
EXTRN dbcs_vector_off:word ;AN000;bgb ; AC000;SM
EXTRN dbcs_vector_seg:word ;AN000;bgb ; AC000;SM
EXTRN filsiz:WORD ;AN000;bgb
EXTRN read_write_relative:byte ;AN000;bgb
data ends ;AC000;bgb
;*****************************************************************************
; recproc procedures
;*****************************************************************************
code segment public para 'CODE' ;AC000;bgb
pathlabl recproc
public report ;AN000;bgb
public Read_Disk ;AN000;bgb
public Write_Disk ;AN000;bgb
public Build_String ;AN000;bgb
public ChANge_BlANks ;AN000;bgb
public Check_DBCS_CharACter ;AN000;bgb
.list
;******************************************
; Prints the XXX of YYY bytes recovered message.
; The XXX value is a dword at di+16 on entry.
; The YYY value is a dword (declared as a word) at filsiz.
;*************************************************************
Procedure report,near ; ;AN000;bgb
lea dx,ofmsg_ptr
mov si,[di+16] ;Get the XXX value
mov x_value_lo,si
mov di,[di+18]
mov x_value_hi,di
mov si,filsiz ;Get the YYY value
mov y_value_lo,si
mov di,filsiz+2
mov y_value_hi,di
call display_interface ; AC000;SM
ret
report endp
;========================================================================= ;an005;bgb
; READ_DISK : This routine reads the logical sector count requested. ;an005;bgb
; It will read a maximum of 64k in one read. If more ;an005;bgb
; than 64k exists it will continue looping until ;an005;bgb
; all sectors have been read. ;an005;bgb
; ;an005;bgb
; Inputs : AL - Drive letter ;an005;bgb
; ES:BX - Segment:offset of transfer address ;an005;bgb
; CX - Sector count ;an005;bgb
; DX - 1st sector ;an005;bgb
; ;an005;bgb
; Outputs : Logical sectors read ;an005;bgb
; LOGIC ;an005;bgb
; ***** ;an005;bgb
; adjust es:bx to es:00 ;an005;bgb
; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?)
; DO while there are more sectors to read than sectors-per-64k ;an005;bgb
; set sector-count to sectors-per-64k ;an005;bgb
; perform the disk read ;an005;bgb
; bump the seg addr to the new addr ;an005;bgb
; dec the number of sectors to read by sectors-per-64k ;an005;bgb
; bump the starting sector number by the sectors-per-64k ;an005;bgb
; ENDDO ;an005;bgb
; perform a disk read for less than sectors-per-64k ;an005;bgb
;========================================================================= ;an005;bgb
procedure read_disk ;an005;bgb
savereg <ax,bx,cx,dx,es>
call seg_adj ;an000;calc new seg:off ;an005;bgb
call calc_sp64k ;an000;secs/64k ;an005;bgb
; $DO ; do while more than 64k ;an005;bgb
$$DO1:
cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb
; $LEAVE LE ;an000;yes ;an005;bgb
JLE $$EN1
mov sec_count,cx ;an000;save cx ;an005;bgb
mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb
call read_once ;an000;read it ;an005;bgb
; $LEAVE C ;an005;bgb
JC $$EN1
mov cx,es ;an005;bgb
add cx,paras_per_64k ; adjust transfer area ;an005;bgb
mov es,cx ;an005;bgb
mov cx,sec_count ; restore sector count ;an005;bgb
sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb
add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb
; $ENDDO ;an005;bgb
JMP SHORT $$DO1
$$EN1:
call read_once ;an000;read it ;an005;bgb
restorereg <es,dx,cx,bx,ax>
ret ;an005;bgb
read_disk endp ;an005;bgb
;an005;bgb
;an005;bgb
;***************************************************************************** ;an005;bgb
;Routine name: Read_once ;an005;bgb
;***************************************************************************** ;an005;bgb
; ;an005;bgb
;description: Read in data using Generic IOCtl ;an005;bgb
; ;an005;bgb
;Called Procedures: None ;an005;bgb
; ;an005;bgb
; ;an005;bgb
;Change History: Created 5/13/87 MT ;an005;bgb
; ;an005;bgb
;Input: AL = Drive number (0=A) ;an005;bgb
; DS:BX = Transfer address ;an005;bgb
; CX = Number of sectors ;an005;bgb
; Read_Write_Relative.Start_Sector_High = Number of sectors high ;an005;bgb
; DX = logical sector number low ;an005;bgb
; ;an005;bgb
;Output: CY if error ;an005;bgb
; AH = INT 25h error code ;an005;bgb
; ;an005;bgb
;Psuedocode ;an005;bgb
;---------- ;an005;bgb
; Save registers ;an005;bgb
; Setup structure for function call ;an005;bgb
; Read the disk (AX=440Dh, CL = 6Fh) ;an005;bgb
; Restore registers ;an005;bgb
; ret ;an005;bgb
;***************************************************************************** ;an005;bgb
Procedure Read_once ; ;an005;bgb
savereg <ax,bx,cx,dx,si,di,bp,es,ds> ;Change it to Read relative sect;an005;bgb
mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;an005;bgb
mov bx,es ; ;AN005;bgb
mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;an005;bgb
mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to read ;an005;bgb
mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;an005;bgb
mov bx,offset Read_Write_Relative ; ;an005;bgb
mov cx,0FFFFh ;Read relative sector ;an005;bgb
INT 25h ;Do the read ;an005;bgb
pop dx ;Throw away flags on stack ;an005;bgb
restorereg <ds,es,bp,di,si,dx,cx,bx,ax> ;an005;bgb
return ;an005;bgb
Read_once endp ;an005;bgb
;an005;bgb
;an005;bgb
;========================================================================= ;an005;bgb
; WRITE-DISK : This routine reads the logical sector count requested. ;an005;bgb
; It will read a maximum of 64k in one read. If more ;an005;bgb
; than 64k exists it will continue looping until ;an005;bgb
; all sectors have been read. ;an005;bgb
; ;an005;bgb
; Inputs : AL - Drive letter ;an005;bgb
; ES:BX - Segment:offset of transfer address ;an005;bgb
; CX - Sector count ;an005;bgb
; DX - 1st sector ;an005;bgb
; ;an005;bgb
; Outputs : Logical sectors read ;an005;bgb
; LOGIC ;an005;bgb
; ***** ;an005;bgb
; adjust es:bx to es:00 ;an005;bgb
; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?)
; DO while there are more sectors to read than sectors-per-64k ;an005;bgb
; set sector-count to sectors-per-64k ;an005;bgb
; perform the disk read ;an005;bgb
; bump the seg addr to the new addr ;an005;bgb
; dec the number of sectors to read by sectors-per-64k ;an005;bgb
; bump the starting sector number by the sectors-per-64k ;an005;bgb
; ENDDO ;an005;bgb
; perform a disk read for less than sectors-per-64k ;an005;bgb
;========================================================================= ;an005;bgb
procedure write_disk ;an005;bgb
mov Read_Write_Relative.Start_Sector_High,bp; ;;an027;bgb;an023;bgb
call seg_adj ;an000;calc new seg:off ;an005;bgb
; $DO ; do while more than 64k ;an005;bgb
$$DO5:
cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb
; $LEAVE LE ;an000;yes ;an005;bgb
JLE $$EN5
mov sec_count,cx ;an000;save cx ;an005;bgb
mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb
call write_once ;an000;read it ;an005;bgb
; $LEAVE C ;an005;bgb
JC $$EN5
mov cx,es ;an005;bgb
add cx,paras_per_64k ; adjust transfer area ;an005;bgb
mov es,cx ;an005;bgb
mov cx,sec_count ; restore sector count ;an005;bgb
sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb
add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb
; $ENDDO ;an005;bgb
JMP SHORT $$DO5
$$EN5:
call write_once ;an000;read it ;an005;bgb
ret ;an005;bgb
write_disk endp ;an005;bgb
;an005;bgb
;*****************************************************************************
;Routine name: Write_Once
;*****************************************************************************
;
;description: Write Data using int 26
;
;Called Procedures: None
;
;
;Change History: Created 5/13/87 MT
;
;Input: AL = Drive number (0=A)
; DS:BX = Transfer address
; CX = Number of sectors
; Read_Write_Relative.Start_Sector_High = Number of sectors high
; DX = logical sector number low
;
;Output: CY if error
; AH = INT 26h error code
;
;Psuedocode
;----------
; Save registers
; Setup structure for function call
; Write to disk (AX=440Dh, CL = 4Fh)
; Restore registers
; ret
;*****************************************************************************
Procedure Write_once ; ;AN000;bgb
savereg <ax,bx,cx,dx,di,si,bp,es,ds> ;This is setup for INT 26h right;AN000;bgb
mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;AN000;bgb
mov bx,es ; ;AN005;bgb
mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;AN000;bgb
mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to write ;AN000;bgb
mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;AN000;bgb
mov cx,0FFFFh ;Write relative sector ;AN000;bgb
lea bx,read_write_relative ;
INT 026h ;Do the write ;AN000;bgb
pop dx ;flags is returned on the stack;AN000;bgb
restorereg <ds,es,bp,si,di,dx,cx,bx,ax> ; ;AN000;bgb
ret ; ;AN000;bgb
Write_once endp ; ;AN000;bgb
;========================================================================= ;an005;bgb
; SEG_ADJ : This routine adjusts the segment:offset to prevent ;an005;bgb
; address wrap. ;an005;bgb
; ;an005;bgb
; Inputs : bx - Offset to adjust segment with ;an005;bgb
; es - Segment to be adjusted ;an005;bgb
; ;an005;bgb
; Outputs : bx - New offset ;an005;bgb
; es - Adjusted segment ;an005;bgb
;========================================================================= ;an005;bgb
procedure seg_adj ;an005;bgb
savereg <ax,cx,dx> ;an005;bgb
mov ax,bx ;an000;get offset ;an005;bgb
mov bx,0010h ;divide by 16 ;an005;bgb
xor dx,dx ;an000;clear dx ;an005;bgb
div bx ;an000;get para count ;an005;bgb
mov bx,es ;an000;get seg ;an005;bgb
add bx,ax ;an000;adjust for paras ;an005;bgb
mov es,bx ;an000;save new seg ;an005;bgb
mov bx,dx ;an000;new offset ;an005;bgb
restorereg <dx,cx,ax> ;an005;bgb
ret ;an005;bgb
seg_adj endp ;an005;bgb
;an005;bgb
;an005;bgb
;========================================================================= ;an005;bgb
; SECS_PER_64K : This routine calculates how many sectors, for this ;an005;bgb
; particular media, will fit into 64k. ;an005;bgb
; ;an005;bgb
; Inputs : DPB_SECTOR_SIZE - bytes/sector ;an005;bgb
; ;an005;bgb
; Outputs : SECS_PER_64K - Sectors / 64k ;an005;bgb
; PARAS_PER_64K - paragraphs per 64k ;an005;bgb
;========================================================================= ;an005;bgb
procedure calc_sp64k ;an005;bgb
savereg <ax,bx,cx,dx> ;an005;bgb
mov ax,0ffffh ;an000;64k ;an005;bgb
mov bx,bytes_per_sector ;an000;get bytes/sector ;an005;bgb
xor dx,dx ;an000;clear dx ;an005;bgb
div bx ;an000;sector count ;an005;bgb
mov secs_per_64k,ax ;an000;save sector count ;an005;bgb
mov ax,bytes_per_sector ;an000;get bytes/sector ;an005;bgb
mov bx,010h ; divide by paras ;an005;bgb
xor dx,dx ;an000;clear dx ;an005;bgb
div bx ; paras per sector ;an005;bgb
mul secs_per_64k ; times sectors ;an005;bgb
mov paras_per_64k,ax ; = paras per 64k ;an005;bgb
restorereg <dx,cx,bx,ax> ;an000;restore dx ;an005;bgb
ret ;an000; ;an005;bgb
calc_sp64k endp ;an000; ;an005;bgb
;*****************************************************************************
;Routine name: Build_String
;*****************************************************************************
;
;Description: Build AN ASCIIZ string from the FCB filename input.
;
;Called Procedures: None
;
;ChANge History: Created 6/29/87 MT
;
;Input: DS:SI = String containing FCB input
; ES:DI = Where to build string
;
;Output: ES:DI = Input string starting at first non-blANk charACter
;
;Psuedocode
;----------
;
; Save regs
; DO
; LEAVE Next charACter is 0,OR
; LEAVE 12th charACter,OR
; Get charACter
; LEAVE BlANk
; Inc counter
; ENDDO
; Set next charACter to 0
; Restore regs
;
;*****************************************************************************
Procedure Build_String ; ;AN000;
cld ;Set string ops to up ;AN000;
push ax ;Save registers ;AN000;
push cx ; " " " " ;AN000;
push si ;Save pointer reg ;AN000;
xor cx,cx ;Init the counter ;AN000;
; $DO ;Loop until entire string found ;AN000;
$$DO9:
cmp byte ptr [si],ASCIIZ_END ;Is next charACter 0? ;AN000;
; $LEAVE E,OR ;Yes, end loop ;AN000;
JE $$EN9
cmp cx,FCB_Filename_Length ;Looked at 11 chars? ;AN000;
; $LEAVE E,OR ;Yes, end of string ;AN000;
JE $$EN9
lodsb ;Nope, get charACter ;AN000;
cmp al,BlANk ;Find end of filename? ;AN000;
; $LEAVE E ;Yes, quit looping ;AN000;
JE $$EN9
stosb ;Move the char
inc cx ;No, inc counter ANd try next ;AN000;
; $ENDDO ; ;AN000;
JMP SHORT $$DO9
$$EN9:
mov byte ptr [di],ASCIIZ_END ;Make ASCIIZ string ;AN000;
pop si ;Get bACk pointer to string ;AN000;
pop cx ;Restore regsisters ;AN000;
pop ax ; " " " " ;AN000;
ret ; ;AN000;
Build_String endp ; ;AN000;
;*****************************************************************************
;Routine name: ChANge_BlANks
;*****************************************************************************
;
;Description: ReplACe all DBCS blANks with SBCS blANks
;
;Called Procedures: Check_DBCS_CharACter
;
;ChANge History: Created 6/12/87 MT
;
;Input: DS:SI = ASCIIZ string containing volume label input
;
;Output: DS:SI = ASCIIZ string with all DBCS blANks replACed with 2 SBCS blANks
;
;
;Psuedocode
;----------
;
; Save pointer to string
; DO
; LEAVE End of string (0)
; See if DBCS charACter (Check_DBCS_CharACter)
; IF CY (DBCS char found)
; IF first byte DBCS blANk, AND
; IF second byte DBCS blANk
; Convert to SBCS blANks
; ENDIF
; Point to next byte to compensate for DBCS charACter
; ENDIF
; ENDDO
; Restore pointer to string
;
;*****************************************************************************
Procedure ChANge_BlANks ; ;AN000;
; $DO ;Do while not CR ;AN000;
$$DO12:
cmp byte ptr [si],Asciiz_End ;Is it end of string? ;AN000;
; $LEAVE E ;All done if so ;AN000;
JE $$EN12
call Check_DBCS_CharACter ;Test for dbcs lead byte ;AN000;
; $IF C ;We have a lead byte ;AN000;
JNC $$IF14
cmp byte ptr [si],DBCS_Lead ;Is it a lead blANk? ;AN000;
; $IF E,AND ;If a dbcs char ;AN000;
JNE $$IF15
cmp byte ptr [si+1],DBCS_BlANk ;Is it AN AsiAN blANk? ;AN000;
; $IF E ;If AN AsiAN blANk ;AN000;
JNE $$IF15
mov byte ptr [si+1],BlANk ;set up moves ;AN000;
mov byte ptr [si],BlANk ; to replACe ;AN000;
; $ENDIF ; ;AN000;
$$IF15:
inc si ;Point to dbcs char ;AN000;
; $ENDIF ;End lead byte test ;AN000;
$$IF14:
inc si ;Point to si+1 ;AN000;
; $ENDDO ;End do while ;AN000;
JMP SHORT $$DO12
$$EN12:
ret ;return to caller ;AN000;
ChANge_BlANks endp ; ;AN000;
;*****************************************************************************
;Routine name: Check_DBCS_CharACter
;*****************************************************************************
;
;Description: Check if specified byte is in rANges of DBCS vectors
;
;Called Procedures: None
;
;ChANge History: Created 6/12/87 MT
;
;Input: AL = CharACter to check for DBCS lead charACter
; DBCS_Vector = YES/NO
;
;Output: CY set if DBCS charACter
; DBCS_VECTOR = YES
;
;
;Psuedocode
;----------
; Save registers
; IF DBCS vector not found
; Get DBCS environmental vector (INT 21h
; Point at first set of vectors
; ENDIF
; SEARCH
; LEAVE End of DBCS vectors
; EXITIF CharACter > X1,AND (X1,Y1) are environment vectors
; EXITIF CharACter < Y1
; STC (DBCS charACter)
; ORELSE
; Inc pointer to next set of vectors
; ENDLOOP
; CLC (Not DBCS charACter)
; ENDSRCH
; Restore registers
; ret
;*****************************************************************************
Procedure Check_DBCS_CharACter ; ;AN000;
push ds ;Save registers ;AN000;
push si ; " " " " ;AN000;
push ax ; " " " " ;AN000;
push ds ; " " " " ;AN000;
pop es ;Establish addressability ;AN000;
cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;AN000;
push ax ;Save input charACter ;AN000;
; $IF NE ;Nope ;AN000;
JE $$IF19
mov al,0 ;Get DBCS environment vectors ;AN000;
DOS_Call Hongeul ; " " " " ;AN000;
mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector ;AN000;
mov es:DBCS_Vector_Off,si ;Save the vector ;AN000;
mov ax,ds ; ;AN000;
mov es:DBCS_Vector_Seg,ax ; ;AN000;
; $ENDIF ; for next time in ;AN000;
$$IF19:
pop ax ;Restore input charACter ;AN000;
mov si,es:DBCS_Vector_Seg ;Get saved vector pointer ;AN000;
mov ds,si ; ;AN000;
mov si,es:DBCS_Vector_Off ; ;AN000;
; $SEARCH ;Check all the vectors ;AN000;
$$DO21:
cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;AN000;
; $LEAVE E ;Yes, done ;AN000;
JE $$EN21
cmp al,ds:[si] ;See if char is in vector ;AN000;
; $EXITIF AE,AND ;If >= to lower, ANd ;AN000;
JNAE $$IF21
cmp al,ds:[si+1] ; =< thAN higher rANge ;AN000;
; $EXITIF BE ; then DBCS charACter ;AN000;
JNBE $$IF21
stc ;Set CY to indicate DBCS ;AN000;
; $ORELSE ;Not in rANge, check next ;AN000;
JMP SHORT $$SR21
$$IF21:
add si,DBCS_Vector_Size ;Get next DBCS vector ;AN000;
; $ENDLOOP ;We didn't find DBCS char ;AN000;
JMP SHORT $$DO21
$$EN21:
clc ;Clear CY for exit ;AN000;
; $ENDSRCH ; ;AN000;
$$SR21:
pop ax ;Restore registers ;AN000;
pop si ; " " " " ;AN000;
pop ds ;Restore data segment ;AN000;
ret ; ;AN000;
Check_DBCS_CharACter endp ; ;AN000;
pathlabl recproc
code ends
end
|