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
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
|
title MSDOS V2.0 FIND
;--------------------------------------------------------------------;
; Revision History: ;
; ;
; V1.1 8/23/82 M.A.Ulloa ;
; ;
; V1.2 9/22/82 M.A.Ulloa ;
; Added the -c and -n options ;
; ;
; 9/23/82 M.A.Ulloa ;
; Added DOS version number control ;
; ;
; 10/07/82 Rev.2 M.A.Ulloa ;
; Changed quote for double quotes, and added ;
; file name printing ;
; ;
; 10/20/82 Rev.3 M.A.Ulloa ;
; Modified IBM name to FIND, and changed the text ;
; of some messages. ;
; ;
; 10/25/82 Rev.4 M.A.Ulloa ;
; Changed name to FIND and all messages to the ;
; IBM form. ;
; ;
; 10/27/82 Rev.5 M.A.Ulloa ;
; Made the correct exit on version check in case ;
; of a 1.x DOS. ;
; ;
; 11/4/82 Rev. 5 A.R. Reynolds ;
; Messages moved to external module ;
; ;
; 11/10/82 Rev. 6 M.A. Ulloa ;
; Corrected problem with line numbers, and a problem ;
; with seeking for 0 chars. ;
; ;
; 03/30/83 Rev. 7 M.A. Ulloa ;
; Added patch area for bug fixing. ;
; ;
; 04/14/83 Rev. 8 M.A. Ulloa ;
; Made changes for Kanji characters. (uhg!) ;
; ;
;--------------------------------------------------------------------;
FALSE equ 0
TRUE equ NOT FALSE
KANJI equ FALSE ;set to true is kanji vers.
;--------------------------------------------------------------------;
; FIND program following the standart UNIX operation. ;
; ;
; FORMAT: ;
; find {option} string {filename {filename} {...}} ;
; ;
; NOTES: ;
; 1) String arguments HAVE to be enclosed ;
; in double quotes. (Two double quotes if a ;
; doble quote is to be included). Only ONE ;
; string argument is presently allowed. ;
; ;
; 2) Options are available: ;
; v All lines but those matching are considered ;
; c Only print a count of matching lines ;
; n Each line is preceded by its relative ;
; line number in the file. ;
; ;
; - Options can be Upper or lower case. ;
; - Format: The switch character followed by an options ;
; character. I.e.: In the IBM PC: /v ;
; ;
; 3) The program returns: ;
; 0 - OK, and some matches ;
; 2 - Some Error ;
; ;
; 4) The maximum line size is determined by ;
; buffer size. Bigger lines will bomb the program. ;
; ;
; 5) If no file name is given then it will asssume ;
; the input is comming from the Standart Input. NO ;
; errors are reported when reading from Standart Input. ;
;--------------------------------------------------------------------;
code segment public
assume cs:code,ss:code,ds:nothing,es:nothing
CR equ 0dh ;A Carriage Return
LF equ 0ah ;A Line Feed
quote_char equ 22h ;A double quote character
buffer_size equ 4096 ;file buffer size
st_buf_size equ 128 ;string arg. buffer size
fname_buf_size equ 64 ;file name buffer size
;----- DOS EQUATES --------------------------------------------------;
std_in equ 0 ;STD input handle
std_out equ 1 ;STD output handle
std_err equ 2 ;STD error handle
dos_ent equ 21h ;DOS entry point
std_con_string_output equ 9
get_version equ 48
char_oper equ 55 ;get configuration parameters
open equ 61 ;DOS std open code
close equ 62 ;DOS std close code
read equ 63 ;DOS std read code
write equ 64 ;DOS std write code
lseek equ 66 ;DOS file seek
exit equ 76 ;DOS process exit code
;----- Misc Data -----------------------------------------------;
make db "***MAUlloa/Microsoft/V12***"
rev db "8"
colon db ": "
n1_buf db "["
n2_buf db 8 dup(0) ;buffer for number conversion
;----- OPTION FLAGS -------------------------------------------------;
; If a flag is set (0ffh) then the option has been selected, if
;reset (0) then it has been not. All options are reset initially.
; NOTE: the order of this table has to remain consistent with the
;options dispatch code. If any changes are made they have to
;correspond with the code.
opt_tbl:
v_flg db 0
c_flg db 0
n_flg db 0
x_flg db 0 ;not used
l_flg db 0 ;not used
;----- LINE COUNTERS ------------------------------------------------;
mtch_cntr dw 0 ;matched lines counter
line_cntr dw 0 ;line counter
;----- MAIN ROUTINE -------------------------------------------------;
start:
;----- CHECK VERSION NUMBER -----------------------------------------;
mov ah,get_version
int 21h
cmp al,2
jge vers_ok
push cs
pop ds
mov dx,offset bad_vers
mov ah,std_con_string_output
int 21h
push es ;bad vers, exit a la 1.x
xor ax,ax
push ax
badfart proc far ;(what a hack!!)
ret
badfart endp
vers_ok:
push cs ;load ES to the right area,
pop es ; for use with DI register
assume es:code
;--------------------------------------------------------------------;
mov si,81h ;Start addrss. of commad line buf.
call kill_bl ;Get rid of blanks
or bx,bx ;A CR found?
jz find_opt ;no, first find the options
args_missing:
mov dx,offset errmsg1 ;empty command line, no args: error.
mov cl,cs:errlen1
call prt_err
mov al,2 ;error code for exit
jmp done
;----- FIND THE OPTION IF ANY ---------------------------------------;
find_opt:
mov ah,char_oper ;get the dos switch char.
mov al,0
int dos_ent ;switch char in DL
push dx
another_opt:
lodsb ;get the first char of command line
cmp al,' ' ;a blank?
je cont_scan
cmp al,CR ;a Carriage Return
je args_missing
pop dx ;get switch character
cmp al,dl ;is it the switch char?
jne find_str ;no, no options: get the string
push dx ;save for another round
lodsb ;get the option character
cmp al,' ' ;a blank?
je cont_scan ;yes, ignore and continue
cmp al,CR ;a CR?
je args_missing ;yes, error...
call make_caps ;Capitalize the character
mov bx,offset opt_tbl ;pointer to option flag table
cmp al,'V' ;the v option?
je opt_v
cmp al,'C' ;the c option?
je opt_c
cmp al,'N' ;the n option?
je opt_n
mov cs:errmsg5_opt,al ;save the option
mov dx,offset errmsg5 ;unknown option: error
mov cl,cs:errlen5
call prt_err
mov dx,offset crlf ;print a CRLF
mov cx,2
call prt_err
jmp another_opt ;process next option
opt_v:
mov di,0
jmp short opt_dispatch
opt_c:
mov di,1
jmp short opt_dispatch
opt_n:
mov di,2
opt_dispatch:
mov es:byte ptr[bx+di],0ffh ;set the corresponding flag
jmp another_opt ;process the rest of the options
cont_scan:
dec si ;adjust SI
call kill_bl ;get rid of blanks
or bx,bx ;A CR found?
jz another_opt ;no, test for other options
jmp args_missing ;yes, error...
;----- FIND STRING ARGUMENT -----------------------------------------;
find_str:
cmp al,quote_char ;string should start with a
jnz bad_str_err ; quote character, if not: error.
mov di,offset st_buffer ;String argument buffer addrss.
xor cx,cx ;Clear to keep string length.
move_str:
lodsb
cmp al,CR ;if a CR is found in the string
jnz str_ok ; then it's a bad string
bad_str_err:
mov dx,offset errmsg2 ;bad string error message
mov cl,cs:errlen2
call prt_err ;print the error.
mov al,2
jmp done
str_ok:
cmp al,quote_char ;look for a quote character
jnz move_char ;not an apost., move to buffer
lodsb ;an apost., check next char.
cmp al,quote_char ;another quote character?
je move_char ;yes, move it to the buffer
dec si ;no, adjust the pointer
mov es:st_length,cx ;store the string length
or cx,cx ;Is the string empty?
jnz other_args ;no: get the rest of the args.
mov al,1 ;empty: no matches(!?)
jmp done
move_char:
stosb ;put in buffer
inc cx ;increment string length
jmp move_str
;----- FIND THE FILE ARGUMENTS --------------------------------------;
other_args: ;Process the rest of the command
; line arguments.
call kill_bl ;get rid of leading blanks
or bx,bx ;At least one argument necessary,
jz further_args ; if a CR not found: ok.
;----- USE STD IN FOR INPUT -----------------------------------------;
push cs
pop ds
mov ax,std_in ;handle
jmp fill
further_args:
call clr_cntrs ;set all counters to zero
mov di,offset file_name_buf ;Set pointer to the name buffer
xor cx,cx ;zero file name length
move_fname:
lodsb
cmp al,' ' ;A blank: end of file name,
je done_move
cmp al,CR ;A CR: idem.
je done_move
stosb ;store in name buffer
inc cx ;increment file name length
jmp move_fname
done_move:
dec si ;Adjust pointer for next round.
mov es:byte ptr[di],00h ;File names are null terminated
push si ;Save SI to continue com. line scan.
push ds ;Save DS register contents for
; later because it points to the
; rest of the arguments.
mov es:file_name_len,cx ;save the name length
;----- OPEN FILE FOR READING ----------------------------------------;
push cs ;Load new DS with CS
pop ds
mov dx,offset file_name_buf ;addrss. of the file name
mov ah,open
mov al,0 ;file open for reading
int dos_ent ;call the DOS
jnc say_name ;if no carry then no errors
jmp open_error
;----- PRINT FILE NAME ----------------------------------------------;
say_name:
push ax ;save file handle
mov dx,offset heading
mov cl,cs:heading_len
xor ch,ch
call prout
mov dx,offset file_name_buf
mov cx,ds:file_name_len
call prout
cmp ds:c_flg,0ffh ;count only flag set?
je xx1
mov dx,offset crlf
mov cx,2
call prout
xx1:
pop ax
;----- Fill Buffer for Matching -------------------------------------;
fill:
mov bx,ax ;retrieve handle
refill:
mov dx,offset buffer ;data buffer addrss.
mov cx,buffer_size
mov ah,read
int dos_ent
jnc no_read_error ;if carry then read error
jmp read_error
no_read_error:
or ax,ax ;if ax=0 then all done
jnz go_match
cmp ds:c_flg,0ffh ;count only flag set?
jne sj2
call print_count
sj2:
cmp bx,std_in ;Using STD IN?
jnz regular
jmp foo ;if so: all done, exit
regular:
mov ah,close ;otherwise close the file
int dos_ent
jmp scan_rest ;get another file
;----- MATCH ROUTINE ------------------------------------------------;
;Note: If input is being taken from a file the stack contains
; (from top to bottom):
; - Pointer to the next command in the command line
; - Pointer to the program segment prefix (to be loaded into
; DS to access the command line.
; if the imput is from the standart input then NONE of it will be
; in the stack.
go_match:
push bx ;save the file handle
mov bp,offset buffer ;ptr to first line of file
mov di,ax ;dispalcement from beg of buffer
cmp ax,buffer_size-1 ;last line of the file?
jg no_last_line ;if yes, add a CRLF just in case
mov bx,bp
cmp byte ptr[bx+di-1],LF ;finished with a LF?
je no_last_line ;yes, it's an OK line.
mov byte ptr[bx+di],CR ;put a CR at the end of the data
inc di
mov byte ptr[bx+di],LF ;put a LF ...
inc di
no_last_line:
push di ;save the # of chars. in the buffer
push bp
mov dx,ds:st_length ;length of the string arg.
dec dx ;adjust for later use
jmp short try_again
more_stuff_o:
jmp more_stuff
;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------;
;Note: at this point the stack contains (from top to bottom):
; - Stuff mentioned before
; - File Handle
; - Number of chars. left in the buffer from the next line.
; - Addrs. of the next line in the buffer.
;
; plus, DX has the adjusted length of the string argument.
try_again:
inc ds:line_cntr ;increment line counter
pop bp ;addrs. of next line in the buffer
mov di,bp ;points to beg. of a line
pop cx ;get # of chars left in the buffer
mov bx,cx ;save in case a non-complete line
mov al,LF ;search for a Line Feed
jcxz more_stuff_o ;no chars left in buffer
repnz scasb
jnz more_stuff_o ;no full line left in buffer
push cx ;save chars left in buffer
push di ;points to beg. of next line
mov cx,di
sub cx,bp ;length of the current line
mov bx,cx ;save in case it has a match
dec cx
dec cx ;CRLF characters discounted
jcxz try_again_opt ;if line empty go to next line
mov di,bp ;pointer to the beg. of current line
another_char:
;
; On entry:
; BX line length
; CX adjusted line length
; DX adjusted string argument length
; DI points to beg. of line
;
IF KANJI
push dx ;save for next line
lop:
pop dx
push dx
inc dx ;different algorithm!
mov si,offset st_buffer ;pointer to beg. of string argument
comp_next_char:
push di
mov di,si
call is_prefix ;check for a prefix char
pop di
jnc nopre
lodsw
cmp cx,1 ; Can not compare a two byte char
jz try_again_opt1 ; if there is only one available
cmp ax,word ptr [di]
jz kmatch1
call next_kchar ;no match, advance di to next kanji
jc try_again_opt1 ;not enough chars left in line
jmp short lop ;try another char in line
nopre:
lodsb
cmp al,byte ptr [di]
jz kmatch
call next_kchar ;no match, advance di to next kanji
jc try_again_opt1 ;not enough chars left in line
jmp short lop ;try another char in line
try_again_opt1:
pop dx
jmp try_again_opt
kmatch1:
dec dx ;last char had prefix so it was
; long.
kmatch:
dec dx
jz a_matchk ; no chars left: a match!
call next_kchar
jc try_again_opt1
jmp comp_next_char ; loop if chars left in arg.
a_matchk:
pop dx
ELSE
mov si,offset st_buffer ;pointer to beg. of string argument
lodsb ;get first character of the str. arg.
repnz scasb ;search for a match in current line
jnz try_again_opt ;no match, try the next line
cmp cx,dx ;compare lengths, a full match is not
jb try_again_opt ; possible if CX < DX.
push di ;save addrs. of next char. in the line
push cx ;save the # of chars. left in the line
mov cx,dx ;get the adjusted string arg. length
jcxz a_match ;if a single char string, then match!
repz cmpsb ;compare string with line
jz a_match ;a match found, hurrah!
pop cx ;no match, get # of chars remaining
; in the line.
pop di ;position of the next char. in the line
jmp another_char
;----- A MATCH: CHECK FOR THE v OPTION ------------------------------;
a_match:
pop ax ;adjust stack
pop ax
ENDIF
cmp ds:v_flg,0ffh ;is flag set?
jne prt_line ;no, print the line
jmp try_again
;----- NO MATCH: CHECK FOR THE v OPTION -----------------------------;
try_again_opt:
cmp ds:v_flg,0ffh ;is flag set?
jne try_again ;no goto next line
;----- PRINT THE LINE WITH THE MATCH --------------------------------;
;Note: at this point the stack contains (top to bottom)
; - Stuff mentioned before
;
; plus, BP points to begginig of the current line, BX has the length
;of the current line including the CRLF, and DX the adjusted length of
;the string argument.
prt_line:
cmp ds:c_flg,0ffh ;is count only flag set?
jne no_c_flg
inc ds:mtch_cntr ;yes, increment counter
jmp try_again
no_c_flg:
push dx ;save the adjusted string arg. length
cmp ds:n_flg,0ffh ;is line number flag set?
jne no_n_flg
call prt_lcntr
no_n_flg:
mov dx,bp
mov cx,bx
call prout
pop dx ;restore
jmp try_again
;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------;
; The scanning routines have detected that the buffer does not
;contain a full line any more. More lines have to be read into the
;buffer. But first perform a seek on the file in order to re-read
;the non-complete line into the begining of the buffer.
; Uppon entry BP contains points to the begining of the non-complete
;line, and BX has the number of characters left in the buffer.
; The Stack contains (top to bottom):
; - Pointer to the next command in the command line
; - Pointer to the program segment prefix (to be loaded into
; DS to access the command line).
; - File handle.
more_stuff:
mov dx,bx ;get chars left in buffer
pop bx ;get the handle
or dx,dx ;are there 0 left?
jz no_seek ;yes, do not seek
neg dx ;form two's complement
mov cx,-1
mov al,1 ;seek from the current position
mov ah,lseek ;seek on file
int dos_ent
jc read_error
no_seek:
jmp refill ;no errors: refill the buffer
read_error:
cmp bx,std_in ;Using STD IN?
je foo ;if so: all done, exit
mov ah,close ;close the file
int dos_ent
mov dx,offset errmsg4_pre ;read error
mov cl,cs:errlen4_pre
call prt_file_name ;print the file name in error
mov dx,offset errmsg4_post ;read error
mov cl,cs:errlen4_post
jmp r_error
;----- PRINT ERRORS -------------------------------------------------;
open_error:
mov dx,offset errmsg3_pre ;error in open operation
mov cl,cs:errlen3_pre
call prt_err_2 ;print error message
call prt_file_name ;print the file name in error
mov dx,offset errmsg3_post ;error in open operation
mov cl,cs:errlen3_post
r_error:
call prt_err_2 ;print error message
;----- SCAN THE REST OF THE COMMAND LINE ----------------------------;
scan_rest:
pop ds ;restore pointer to comm. line
pop si ;restore pointer to next comm.
call kill_bl ;look for further args.
or bx,bx ;test for a CR
jnz foo
jmp further_args
foo:
mov al,0 ;Proper code
done:
mov ah,exit ;All done, exit with proper code.
int dos_ent
;--------------------------------------------------------------------;
; Get rid of blanks in command line. ;
; Advances the SI reg till the next non-blank character, if the ;
; character is a CR (0dh) then returns with BX non-zero, otherwise ;
; BX is zero. ;
; ;
; entry: ;
; SI points to the first character on the line to scan. ;
; ;
; exit: ;
; SI points to the first non-blank character found. ;
; BX contains 0D hex if the first non-blank found is ;
; a Carriage Return, otherwise it is 0. ;
; ;
; modifies: ;
; BX, SI, and AX ;
; ;
;--------------------------------------------------------------------;
kill_bl:
cld ;increment
xor bx,bx ;zero bx to start: no CR found
no_bl:
lodsb ;get rid of blanks
cmp al,' '
je no_bl
cmp al,CR
jnz no_cr
mov bx,ax ;make bx non-zero (actually 0dh)
no_cr:
dec si ;adjust pointer
ret
;--------------------------------------------------------------------;
; Clear Counters ;
;--------------------------------------------------------------------;
clr_cntrs:
mov byte ptr es:mtch_cntr,0
mov byte ptr es:line_cntr,0
ret
;--------------------------------------------------------------------;
; Print Count of Matched lines ;
; ;
; Modifies: AX,CX,DX and DI ;
;--------------------------------------------------------------------;
print_count:
push bx ;save handle
cmp bx,std_in ;using std_in?
jz sj3 ;if so do not print file name
mov dx,offset colon
mov cx,2
call prout ;print colon
sj3:
mov ax,ds:mtch_cntr
mov di,offset n2_buf ;buffer for characters
call bin2asc ;convert to ascii
mov dx,offset n2_buf
call prout ;print the number
mov dx,offset crlf
mov cx,2
call prout ;print an end of line
pop bx
ret
;--------------------------------------------------------------------;
; Print relative line number ;
; ;
; Modifies: AX,CX and DI ;
;--------------------------------------------------------------------;
prt_lcntr:
push bx
push dx
mov ax,ds:line_cntr
mov di,offset n2_buf
call bin2asc
mov byte ptr[di],"]"
inc cx
inc cx
mov dx,offset n1_buf
call prout
pop dx
pop bx
ret
;--------------------------------------------------------------------;
; Print string to STD_OUT ;
;--------------------------------------------------------------------;
prout:
mov bx,std_out
mov ah,write
int dos_ent
ret
;--------------------------------------------------------------------;
; Binary to Ascii conversion routine ;
; ;
; Entry: ;
; AX Binary number ;
; DI Points to one past the last char in the ;
; result buffer. ;
; ;
; Exit: ;
; Result in the buffer MSD first ;
; CX Digit count ;
; ;
; Modifies: ;
; AX,BX,CX,DX and DI ;
; ;
;--------------------------------------------------------------------;
bin2asc:
mov bx,0ah
xor cx,cx
go_div:
inc cx
cmp ax,bx
jb div_done
xor dx,dx
div bx
add dl,'0' ;convert to ASCII
push dx
jmp short go_div
div_done:
add al,'0'
push ax
mov bx,cx
deposit:
pop ax
stosb
loop deposit
mov cx,bx
ret
;--------------------------------------------------------------------;
; Print the current file name ;
; ;
; modifies: ;
; DX, CX, BX and AX ;
;--------------------------------------------------------------------;
prt_file_name:
mov dx,offset file_name_buf ;print the file name
mov cx,ds:file_name_len ;retrive file name length
jmp short prt_err_2
;--------------------------------------------------------------------;
; Print an error message to the Standart error ;
; ;
; entry: ;
; DX has the pointer to the message ;
; CX has the length of the message ;
; ;
; modifies: ;
; BX and AX ;
;--------------------------------------------------------------------;
prt_err:
push ds ;Save the current DS
push cs ;Make DS point to the right
pop ds ; place, for DOS use.
call prt_err_2
pop ds
ret
prt_err_2:
xor ch,ch
mov bx,std_err
mov ah,write
int dos_ent ;write error message
ret
;--------------------------------------------------------------------;
; CAPIALIZES THE CHARACTER IN AL ;
; ;
; entry: ;
; AL has the character to Capitalize ;
; ;
; exit: ;
; AL has the capitalized character ;
; ;
; modifies: ;
; AL ;
;--------------------------------------------------------------------;
make_caps:
cmp al,'a'
jb no_cap
cmp al,'z'
jg no_cap
and al,0dfh
no_cap:
ret
IF KANJI
;--------------------------------------------------------------------;
; ADVANCE POINTER TO NEXT KANJI CHARACTER ;
; ;
; entry: DI points to a Kanji string ;
; CX length in bytes of the string ;
; ;
; exit: DI points to next Kanji char ;
; CX has number of bytes left ;
; ;
; modifies: AX ;
; ;
;--------------------------------------------------------------------;
next_kchar:
jcxz no_kleft
call is_prefix
jnc no_p
inc di
dec cx
jcxz no_kleft ; for insurance
no_p:
inc di
dec cx
clc
ret
no_kleft:
stc
ret
;--------------------------------------------------------------------;
; FIND OUT IS THE BYTE IS A KANJI PREFIX ;
; ;
; entry: DI points to a kanji string ;
; ;
; exit: Carry set if it is a kanji prefix ;
; ;
; modifies: AX ;
; ;
;--------------------------------------------------------------------;
is_prefix:
mov al,byte ptr [di]
cmp al,81h
jb nok
cmp al,0a0h
jb isk
cmp al,0e0h
jb nok
cmp al,0fdh
jb isk
nok:
clc
ret
isk:
stc
ret
ENDIF
;----- PATCH AREA ---------------------------------------------------;
patch_area dw 100h dup(?)
;----- BUFFER AREA --------------------------------------------------;
st_length dw 0 ;String argumnet length
st_buffer db st_buf_size dup(?) ;String argument buffer
file_name_len dw 0 ;File name length
file_name_buf db fname_buf_size+1 dup(?) ;File name buffer,(allow for
; null at the end).
buffer db buffer_size+1 dup(?) ;file buffer, the last byte is
;a guard in case of forced insertion
;of a CRLF pair.
;----- ERROR MESSAGES -----------------------------------------------;
EXTRN bad_vers:byte,crlf:byte,errmsg1:byte,errlen1:byte,errmsg2:byte
EXTRN errmsg3_pre:byte,errlen3_pre:byte
EXTRN errmsg3_post:byte,errlen3_post:byte
EXTRN errmsg4_pre:byte,errlen4_pre:byte
EXTRN errmsg4_post:byte,errlen4_post:byte
EXTRN heading:byte,heading_len:byte,errlen2:byte
EXTRN errmsg5:byte,errmsg5_opt:byte,errlen5:byte
code ends
;----- STACK AREA ---------------------------------------------------;
stack segment stack
dw 64 dup(?,?)
stack_top equ $
stack ends
end start
|