add directory docs
This commit is contained in:
494
docs/interrupts/inter61/COMBINE.ASM
Normal file
494
docs/interrupts/inter61/COMBINE.ASM
Normal file
@@ -0,0 +1,494 @@
|
||||
; COMBINE.ASM Interrupt List combiner
|
||||
; by Ralf Brown
|
||||
; last edit: 22mar98
|
||||
|
||||
NAME COMBINE
|
||||
TITLE Combine Interrupt List sections
|
||||
|
||||
; declare all the segments in the order in which they are to appear in the
|
||||
; executable
|
||||
CODE SEGMENT 'CODE'
|
||||
CODE ENDS
|
||||
STACKSEG SEGMENT PUBLIC WORD 'STACK'
|
||||
STACKSEG ENDS
|
||||
BUFFERSEG SEGMENT PUBLIC WORD 'DATA'
|
||||
BUFFERSEG ENDS
|
||||
;
|
||||
DGROUP GROUP CODE,STACKSEG,BUFFERSEG
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
FFBLK struc
|
||||
ff_reserved db 15h dup (?)
|
||||
ff_attrib db ?
|
||||
ff_ftime dw ?
|
||||
ff_fdate dw ?
|
||||
ff_fsize dd ?
|
||||
ff_fname db 13 dup (?)
|
||||
FFBLK ends
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
CODE SEGMENT 'CODE'
|
||||
ORG 100h ; this is a .COM file
|
||||
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
|
||||
|
||||
combine:
|
||||
jmp near ptr main
|
||||
|
||||
banner db 13,"COMBINE v2.10",9,"Ralf Brown 1996,1998",13,10,"$",26
|
||||
usage_msg db "Usage:",9,"COMBINE [options] dest-dir",13,10
|
||||
db 9,"where {dest-dir} is the directory in which to place",13,10
|
||||
db 9," the combined list ('.' for the current directory)",13,10
|
||||
db 10
|
||||
db 9,"options:",13,10
|
||||
db 9,9,"-d",9,"delete sections after copying",13,10
|
||||
db 9,9,"-p",9,"combine PORTS.LST instead of INTERRUP.LST",13,10
|
||||
db 10
|
||||
db "All sections of the interrupt/ports list must be in the current directory."
|
||||
db "$"
|
||||
|
||||
bad_dos_msg db "Need DOS 2.0+$"
|
||||
bad_drive_msg db "Invalid destination drive$"
|
||||
no_mem_msg db "Insufficient memory$"
|
||||
no_files_msg db "No section files found!$"
|
||||
readerr_msg db "Read Error$"
|
||||
writeerr_msg db "Write Error$"
|
||||
diskfull_msg db "Disk full? while writing$"
|
||||
no_disk_msg db "Out of space on destination drive",13,10,"$"
|
||||
retry_msg db "Try again with -d to delete while copying$"
|
||||
|
||||
cant_create_msg db "Check directory name -- unable to create "
|
||||
combined_file db "INTERRUP.LST",0,"$"
|
||||
combined_file2 db "PORTS.LST",0
|
||||
combined_file2_len equ $-combined_file2
|
||||
section_file1 db "INTERRUP.A",0,"$"
|
||||
section_letter equ section_file1+9
|
||||
section_file2 db " PORTS"
|
||||
section_file2_len equ $-section_file2
|
||||
section_file2_ofs equ 3
|
||||
missing_msg db "unavailable (skipped)"
|
||||
crlf db 13,10,"$"
|
||||
section_heading1 db "Interrupt List, part "
|
||||
section_hdr_len1 equ $-section_heading1
|
||||
section_heading2 db "Ports List, part "
|
||||
section_hdr_len2 equ $-section_heading2
|
||||
complete_msg db "Done.$"
|
||||
|
||||
;
|
||||
; flags affecting operation
|
||||
;
|
||||
del_after_copy db 0
|
||||
section_file dw offset section_file1
|
||||
section_heading dw offset section_heading1
|
||||
section_hdr_len dw section_hdr_len1
|
||||
|
||||
;
|
||||
; data needed while processing
|
||||
;
|
||||
filehandle equ di ; output file's handle
|
||||
numsections db 26
|
||||
dest_drive db 0
|
||||
nondefault_dest db 0
|
||||
ftime dw 0
|
||||
fdate dw 0
|
||||
filesize_lo dw 0
|
||||
filesize_hi equ bp
|
||||
|
||||
; (since we don't use disk_buffer until after FindFirst is no longer needed,
|
||||
; save memory by overlaying the two)
|
||||
FindFirst equ DGROUP:disk_buffer
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
write_string:
|
||||
mov ah,9
|
||||
int 21h
|
||||
ret
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
skip_whitespace:
|
||||
lodsb
|
||||
cmp al,' '
|
||||
je skip_whitespace
|
||||
cmp al,9
|
||||
je skip_whitespace
|
||||
dec si ; unget the last character
|
||||
; set ZF to indicate whether we got to end of cmdline
|
||||
cmp al,0Dh
|
||||
ret
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
get_destination_file:
|
||||
mov bx,si ; remember start of destination name
|
||||
get_dest_file_loop:
|
||||
lodsb
|
||||
cmp al,' '
|
||||
je got_dest_end
|
||||
cmp al,9
|
||||
je got_dest_end
|
||||
cmp al,0Dh
|
||||
jne get_dest_file_loop
|
||||
got_dest_end:
|
||||
dec si ; unget last character
|
||||
mov di,si
|
||||
mov al,[si-1] ; check end of path -- is it terminated
|
||||
cmp al,'\' ; by a slash or backslash?
|
||||
je dest_has_slash
|
||||
cmp al,'/'
|
||||
je dest_has_slash
|
||||
cmp al,':'
|
||||
je dest_has_slash
|
||||
mov al,'\'
|
||||
stosb
|
||||
dest_has_slash:
|
||||
mov si,offset combined_file
|
||||
dest_copy_loop:
|
||||
lodsb
|
||||
stosb
|
||||
cmp al,0
|
||||
jne dest_copy_loop
|
||||
; OK, now open the destination file
|
||||
; (BX is still pointing at start of pathname)
|
||||
cmp byte ptr [bx+1],':'
|
||||
jne got_dest_drive
|
||||
mov al,[bx]
|
||||
and al,0DFh ; force to uppercase
|
||||
sub al,'A'
|
||||
jb got_dest_drive
|
||||
cmp al,dest_drive
|
||||
je got_dest_drive
|
||||
mov dest_drive,al
|
||||
mov nondefault_dest,al
|
||||
got_dest_drive:
|
||||
mov ah,3Ch ; create the output file
|
||||
xor cx,cx ; no special file attributes
|
||||
mov dx,bx
|
||||
int 21h
|
||||
mov dx,offset cant_create_msg
|
||||
jc exit_with_err_2
|
||||
mov filehandle,ax
|
||||
ret
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
check_total_size:
|
||||
mov byte ptr section_letter,'A'-1
|
||||
mov ah,1Ah ; set DTA
|
||||
mov dx,offset FindFirst
|
||||
int 21h
|
||||
xor si,si ; keep track of # of sections found
|
||||
check_size_loop:
|
||||
inc byte ptr section_letter
|
||||
cmp byte ptr section_letter,'Z'
|
||||
ja short get_free_space
|
||||
mov ah,4Eh ; find first
|
||||
mov cx,001Fh ; ...regardless of attribute
|
||||
mov dx,section_file
|
||||
int 21h
|
||||
jc check_size_loop
|
||||
inc si ; another section found
|
||||
mov ax,FindFirst.ff_ftime
|
||||
mov ftime,ax
|
||||
mov ax,FindFirst.ff_fdate
|
||||
mov fdate,ax
|
||||
mov ax,word ptr FindFirst.ff_fsize
|
||||
mov dx,word ptr FindFirst.ff_fsize+2
|
||||
cmp del_after_copy,0
|
||||
je count_full_size
|
||||
cmp nondefault_dest,0
|
||||
jnz count_full_size
|
||||
cmp dx,filesize_hi
|
||||
jb check_size_loop
|
||||
ja check_size_bigger
|
||||
cmp ax,filesize_lo
|
||||
jbe check_size_loop
|
||||
check_size_bigger:
|
||||
mov filesize_lo,ax
|
||||
mov filesize_hi,dx
|
||||
jmp check_size_loop
|
||||
|
||||
count_full_size:
|
||||
add filesize_lo,ax
|
||||
adc filesize_hi,dx
|
||||
jmp check_size_loop
|
||||
|
||||
get_free_space:
|
||||
test si,si ; check number of sections found
|
||||
mov dx,offset no_files_msg
|
||||
jz short exit_with_err_2
|
||||
mov dl,dest_drive
|
||||
inc dx
|
||||
mov ah,36h ; get free disk space
|
||||
int 21h
|
||||
cmp ax,0FFFFh
|
||||
jne got_free_space
|
||||
mov dx,offset bad_drive_msg
|
||||
exit_with_err_2:
|
||||
jmp near ptr exit_with_errmsg
|
||||
got_free_space:
|
||||
mul cx ; DX:AX <- AX*CX
|
||||
mov cx,dx ; store high half of intermediate
|
||||
mul bx ; DX:AX <- low(AX*CX)*BX
|
||||
xchg ax,bx ; store low half of second interm.
|
||||
xchg cx,dx ; store high half of second interm.
|
||||
mul dx ; DX:AX <- high(AX*CX)*BX
|
||||
xchg ax,bx ; DX:BX:0000h + CX:AX = result
|
||||
add bx,cx
|
||||
adc dx,0 ; DX:BX:AX = AX*BX*CX = free space
|
||||
jnz plenty_free_space ; >4G free?
|
||||
sub ax,filesize_lo
|
||||
sbb bx,filesize_hi
|
||||
jnb plenty_free_space
|
||||
not_enough_space:
|
||||
mov dx,offset no_disk_msg
|
||||
call write_string
|
||||
cmp nondefault_dest,0
|
||||
jnz size_check_failed
|
||||
cmp del_after_copy,0
|
||||
jne size_check_failed
|
||||
mov dx,offset retry_msg
|
||||
call write_string
|
||||
size_check_failed:
|
||||
mov al,2
|
||||
jmp exit
|
||||
plenty_free_space:
|
||||
ret
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
check_section_header:
|
||||
push si
|
||||
push di
|
||||
mov si,offset DGROUP:disk_buffer
|
||||
mov di,section_heading
|
||||
mov cx,section_hdr_len
|
||||
or cx,cx
|
||||
rep cmpsb
|
||||
jnz not_section_heading
|
||||
scan_curr_section:
|
||||
lodsb
|
||||
cmp al,' ' ; scan for the " of "
|
||||
jne scan_curr_section
|
||||
add si,3 ; skip "of "
|
||||
xor cl,cl
|
||||
num_sections_loop:
|
||||
lodsb
|
||||
sub al,'0'
|
||||
jb num_sections_done
|
||||
cmp al,9
|
||||
ja num_sections_done
|
||||
mov ch,al
|
||||
mov al,10
|
||||
mul cl
|
||||
mov cl,al
|
||||
add cl,ch
|
||||
jmp num_sections_loop
|
||||
num_sections_done:
|
||||
mov numsections,cl
|
||||
got_num_sections:
|
||||
not_section_heading:
|
||||
pop di
|
||||
pop si
|
||||
ret
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
; in: SI = file handle for current section
|
||||
copy_section:
|
||||
mov ax,4201h
|
||||
xor cx,cx
|
||||
xor dx,dx
|
||||
mov bx,filehandle
|
||||
int 21h
|
||||
mov filesize_lo,ax
|
||||
mov filesize_hi,dx
|
||||
copy_section_loop:
|
||||
mov ah,3Fh
|
||||
mov bx,si
|
||||
mov cx,disk_buffer_end - disk_buffer
|
||||
mov dx,offset DGROUP:disk_buffer
|
||||
int 21h
|
||||
jc copy_read_error
|
||||
mov cx,ax ; write same number of bytes read
|
||||
mov ah,40h
|
||||
;; mov dx,offset DGROUP:disk_buffer
|
||||
mov bx,filehandle
|
||||
int 21h
|
||||
mov dx,offset writeerr_msg
|
||||
jc copy_error
|
||||
mov dx,offset diskfull_msg
|
||||
cmp ax,cx
|
||||
jb copy_error
|
||||
; check for section header at start of buffer, and extract number
|
||||
; of sections from it
|
||||
push cx
|
||||
call check_section_header
|
||||
pop ax
|
||||
cmp ax,disk_buffer_end - disk_buffer ; continue until only partial
|
||||
je copy_section_loop ; buffer read (EOF hit)
|
||||
ret
|
||||
|
||||
copy_read_error:
|
||||
mov dx,offset readerr_msg
|
||||
copy_error:
|
||||
; truncate output to size before section was started
|
||||
push dx ; store error message
|
||||
mov ax,4200h
|
||||
mov cx,filesize_hi
|
||||
mov dx,filesize_lo
|
||||
mov bx,filehandle
|
||||
int 21h
|
||||
mov ah,40h
|
||||
xor cx,cx ; write zero bytes to truncate
|
||||
int 21h
|
||||
pop dx ; get back error message
|
||||
;; fall through to exit_with_errmsg ;;
|
||||
|
||||
;;------------------------------------------------------------------------
|
||||
|
||||
exit_with_errmsg:
|
||||
call write_string
|
||||
; exit with errorlevel 1
|
||||
mov al,01h
|
||||
jmp near ptr exit
|
||||
|
||||
main:
|
||||
ASSUME CS:DGROUP, DS:DGROUP, ES:DGROUP, SS:DGROUP
|
||||
mov dx,offset banner
|
||||
call write_string
|
||||
; relocate the stack
|
||||
mov sp,offset DGROUP:stackbot
|
||||
; ensure that we have enough memory
|
||||
mov ax,cs
|
||||
add ax,1000h ; require 64K memory
|
||||
cmp ax,ds:[0002h] ; is end of mem at least 64K above CS?
|
||||
mov dx,offset no_mem_msg
|
||||
ja exit_with_errmsg
|
||||
mov si,81h ; point at start of cmdline
|
||||
mov bl,[si-1] ; get length of cmdline
|
||||
mov bh,0
|
||||
mov byte ptr [bx+si],0Dh ; ensure cmdline properly terminated
|
||||
cld
|
||||
call skip_whitespace
|
||||
mov dx,offset usage_msg
|
||||
jz exit_with_errmsg
|
||||
get_cmdline_switches:
|
||||
call skip_whitespace
|
||||
jz not_a_switch
|
||||
cmp al,'-' ; is it a switch?
|
||||
jne not_a_switch
|
||||
lodsb ; get the switch character
|
||||
lodsb ; get the switch itself
|
||||
and al,0DFh ; force to uppercase
|
||||
cmp al,'P'
|
||||
je want_ports
|
||||
cmp al,'D'
|
||||
;; mov dx,offset usage_msg
|
||||
jne exit_with_errmsg
|
||||
mov del_after_copy,1
|
||||
jmp get_cmdline_switches
|
||||
want_ports:
|
||||
jmp config_for_ports
|
||||
not_a_switch:
|
||||
mov ah,19h ; get default drive
|
||||
int 21h
|
||||
mov dest_drive,al
|
||||
mov ah,30h
|
||||
int 21h
|
||||
cmp al,2
|
||||
mov dx,offset bad_dos_msg
|
||||
jb exit_with_errmsg
|
||||
call get_destination_file
|
||||
xor filesize_hi,filesize_hi
|
||||
call check_total_size
|
||||
;
|
||||
; OK, all the preliminaries are done now, so go concatenate the
|
||||
; sections of the interrupt list
|
||||
;
|
||||
mov al,'A'-1
|
||||
concat_loop:
|
||||
inc ax
|
||||
mov section_letter,al
|
||||
sub al,'A'-1
|
||||
cmp al,numsections
|
||||
ja concat_done
|
||||
mov dx,section_file
|
||||
call write_string
|
||||
mov ax,3D00h
|
||||
int 21h
|
||||
mov dx,offset missing_msg
|
||||
jc concat_loop_end
|
||||
mov si,ax
|
||||
call copy_section
|
||||
mov bx,si ; BX <- section file's handle
|
||||
mov ah,3Eh ; DOS function: close file handle
|
||||
int 21h
|
||||
cmp del_after_copy,0
|
||||
je concat_no_del
|
||||
mov ah,41h ; DOS function: delete file
|
||||
mov dx,section_file
|
||||
int 21h
|
||||
concat_no_del:
|
||||
mov dx,offset crlf
|
||||
concat_loop_end:
|
||||
call write_string
|
||||
mov al,section_letter
|
||||
jmp concat_loop
|
||||
|
||||
concat_done:
|
||||
mov dx,offset complete_msg
|
||||
call write_string
|
||||
mov al,00h ; successful completion
|
||||
exit:
|
||||
push ax
|
||||
mov dx,offset crlf
|
||||
call write_string
|
||||
mov ax,5701h ; (set file time & date)
|
||||
mov bx,filehandle
|
||||
mov cx,ftime ; set timestamp of combined file to
|
||||
mov dx,fdate ; be that of the last of the sections
|
||||
int 21h
|
||||
mov ah,3Eh ; DOS function: close file handle
|
||||
int 21h
|
||||
pop ax
|
||||
mov ah,4Ch
|
||||
int 21h
|
||||
|
||||
config_for_ports:
|
||||
mov section_heading,offset section_heading2
|
||||
mov section_hdr_len,section_hdr_len2
|
||||
push di
|
||||
push si
|
||||
push cx
|
||||
;; copy combined_file2 over combined_file
|
||||
mov cx,combined_file2_len
|
||||
mov si,offset combined_file2
|
||||
mov di,offset combined_file
|
||||
rep movsb
|
||||
;; copy section_file2 over section_file1
|
||||
mov cx,section_file2_len
|
||||
mov si,offset section_file2
|
||||
mov di,offset section_file1
|
||||
rep movsb
|
||||
pop cx
|
||||
pop si
|
||||
pop di
|
||||
add section_file,section_file2_ofs
|
||||
jmp get_cmdline_switches
|
||||
|
||||
CODE ENDS
|
||||
|
||||
STACKSEG SEGMENT PUBLIC WORD 'STACK'
|
||||
stacktop dw 160 dup (?)
|
||||
stackbot label byte
|
||||
STACKSEG ENDS
|
||||
|
||||
BUFFERSEG SEGMENT PUBLIC WORD 'DATA'
|
||||
disk_buffer db 62*1024 dup (?)
|
||||
disk_buffer_end label byte
|
||||
BUFFERSEG ENDS
|
||||
|
||||
END combine
|
||||
Reference in New Issue
Block a user