;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */ Title E2BINIT(EXE2BIN) ;***************************************************************************** ; Loader for EXE files under 86-DOS ; VER 1.5 ; 05/21/82 Added rev number ; VER 1.6 ; 07/01/82 A little less choosy about size matches ; VER 2.0 M.A.U ; 10/08/82 Modified to use new 2.0 system calls for file i/o ; Ver 2.1 M.A.U ; 10/27/82 Added the DOS version check ; Ver 2.2 MZ ; 8/30/83 Fixed command line parsing ; Ver 2.3 EE ; 10-12-83 More fixes to command line parsing ; Ver 2.4 NP ; 10/17/83 Use Printf for messages ; Ver 2.5 MZ Fix LOCATE sss D: problem ; 04/09/87 Add PARSER and MESSAGE RETRIEVER ; Ver 4.00 DRM ; ; M001 MD 12/27/90 Removed special checks for ambiguous ; file names ;***************************************************************************** INCLUDE SYSMSG.INC MSG_UTILNAME ;AN000; subttl Main Code Area ;AN000; page ; The following switch allows use with the "old linker", which put a version ; number where the new linker puts the number of bytes used in the last page. ; If enabled, this will cause a test for 0004 at this location (the old linker ; version number), and if equal, change it to 200H so all of the last page ; will be used. OLDLINK EQU 0 ;1 to enable, 0 to disable CODE SEGMENT PARA PUBLIC 'CODE' ;AN000; CODE ENDS ;AN000; DATA SEGMENT PARA PUBLIC 'DATA' ;AN000; DATA ENDS ;AN000; STACK SEGMENT PARA PUBLIC 'STACK' ;AN000; STACK ENDS ;AN000; ZLOAD SEGMENT PARA PUBLIC 'ZLOAD' ;AN000; ZLOAD ENDS ;AN000; DATA SEGMENT PARA PUBLIC 'DATA' ;AN000; MSG_SERVICES ;AN000; Command_Line_Buffer db 128 dup(0) ;AN000; Command_Line_Length equ $ - Command_Line_Buffer ;AN000; Fatal_Error db 0 ;AN000; Command_Line db NO rev db "2.4" file1_ext db ".EXE",00h file2_ext db ".BIN",00h per11 db 0 ;AN000; per2 db 0 per22 db 0 ;AN000; update equ 0 ;AN000; noupdate equ -1 ;AN000; file1 db (64+13) dup(?) fnptr dw offset file1 ; Ptr to filename in file1 handle1 dw 1 dup(?) file2 db (64+13) dup(?) f2cspot dw offset file2 ; Ptr to spot in file2, file1 maybe added name2_given db 1 ;1-> atleast the file2 name is present ext2_given db 0 ;1-> full file2 spec given file2_given db 0 ; is TRUE if user specified atleast a ; drive, or path (or full name) handle2 dw 1 dup(?) dma_buf db 80h dup(0) ; DMA transfer buffer INBUF DB 5,0 DB 5 DUP(?) ;The following locations must be defined for storing the header: RUNVAR LABEL BYTE ;Start of RUN variables RELPT DW ? LASTP LABEL WORD RELSEG DW ? SIZ LABEL WORD ;Share these locations PAGES DW ? RELCNT DW ? HEADSIZ DW ? DW ? LOADLOW DW ? INITSS DW ? INITSP DW ? DW ? INITIP DW ? INITCS DW ? RELTAB DW ? RUNVARSIZ EQU $-RUNVAR DBCS_Vector_Off dw 0 ;AN000; DBCS_Vector_Seg dw 0 ;AN000; parse_ptr DW ? DATA ENDS STACK SEGMENT PARA PUBLIC 'STACK' DB (362 - 80h) + 80H DUP (?) ; (362 - 80h) is IBMs ROM requirement ; (New - Old) == size of growth STACK ENDS ; ZLOAD SEGMENT PARA PUBLIC 'ZLOAD' db ? ZLOAD ENDS LOAD EQU ZLOAD ; ; ;***************************************************************************** ; Include files ;***************************************************************************** ; .xlist INCLUDE DOSSYM.INC ; also versiona.inc ;AN000; INCLUDE SYSCALL.INC ;AN000; INCLUDE E2BMACRO.INC ;AN000; INCLUDE E2BEQU.INC ;AN000; INCLUDE E2BTABLE.INC ;AN000; INCLUDE E2BPARSE.INC ;AN000; include version.inc .list CODE SEGMENT PARA PUBLIC 'CODE' assume cs:CODE,ds:DATA,es:NOTHING,SS:STACK ;AN000; psp_ptr dw 1 dup(?) ;AN000; ; ;***************************************************************************** ; SysDisplayMsg Declarations ;***************************************************************************** ; .xlist MSG_SERVICES ;AN000; MSG_SERVICES ;AN000; MSG_SERVICES ;AN000; MSG_SERVICES ;AN000; MSG_SERVICES ;AN000; .list ; ;***************************************************************************** ; External Routine Declarations ;***************************************************************************** ; public SysDispMsg ;AN000; public SysLoadMsg ;AN000; ;***************************************************************************** ;Routine name: Main_Init ;***************************************************************************** ; ;Description: Main control routine for init section ; ;Called Procedures: Message (macro) ; Check_DOS_Version ; Init_Input_Output ; Validate_Target_Drive ; Hook_CNTRL_C ; ;Input: None ; ;Output: None ; ;Change History: Created 6/22/87 DM ; ;***************************************************************************** procedure Main_Init near ; ;AN000; ASSUME DS:NOTHING ; THIS IS WHAT dos GIVES YOU ;AN000; ASSUME ES:NOTHING ;AN000; PUSH DS ;AN000; mov psp_ptr,ds ;AN000; XOR AX,AX ;AN000; PUSH AX ;Push return address to DS:0 ;AN000; MOV AX,SEG DATA ;SET UP ADDRESSABILITY TO ;AN000; MOV DS,AX ; THE DATA SEGMENT ;AN000; ASSUME DS:DATA ;TELL ASSEMBLER WHAT I JUST DID ;AN000; mov Fatal_Error,No ;Init the error flag ;AN000; call Init_Input_Output ;Setup messages and parse ;AN000; cmp Fatal_Error,Yes ;Error occur? ;AN000; ; $IF NE ;Nope, keep going ;AN000; JE $$IF1 call LOCATE ;Go do the real program ;AN000; ; $ENDIF ;AN000; $$IF1: xor al,al ;AN000; Dos_call Exit ;AN000; int 20h ;If other exit fails ;AN000; Main_Init endp ;AN000; ;***************************************************************************** ;Routine name: Init_Input_Output ;***************************************************************************** ; ;Description: Initialize messages, Parse command line, allocate memory as ; needed. If there is a /FS switch, go handle it first as ; syntax of IFS format may be different from FAT format. ; ;Called Procedures: Preload_Messages ; Parse_For_FS_Switch ; Parse_Command_Line ; Interpret_Parse ; ;Change History: Created 6/22/87 DM ; ;Input: PSP command line at 81h and length at 80h ; Fatal_Error = No ; ;Output: Fatal_Error = YES/NO ; ;***************************************************************************** procedure Init_Input_Output near ;AN000; call Preload_Messages ;Load up message retriever ;AN000; cmp Fatal_Error,YES ;Quit? ;AN000; ; $IF NE ;Nope, keep going ;AN000; JE $$IF3 call Parse_Command_Line ;Parse in command line input ;AN000; ; $ENDIF ;AN000; $$IF3: ret ;AN000; Init_Input_Output endp ;AN000; ;***************************************************************************** ;Routine name: Preload_Messages ;***************************************************************************** ; ;Description: Preload messages using common message retriever routines. ; ;Called Procedures: SysLoadMsg ; ; ;Change History: Created 6/22/87 DM ; ;Input: Fatal_Error = NO ; ;Output: Fatal_Error = YES/NO ; ;***************************************************************************** procedure Preload_Messages near ;AN000; call SYSLOADMSG ;Preload the messages ;AN000; ; $IF C ;Error? ;AN000; JNC $$IF5 call SYSDISPMSG ;AN000; mov fatal_error, YES ;AN000; ; $ENDIF ;AN000; $$IF5: ret ;AN000; Preload_Messages endp ;AN000; ;***************************************************************************** ;Routine name: Parse_Command_Line ;***************************************************************************** ; ;Description: Parses command line. ; ;Called Procedures: Message (macro) ; Sysparse ; ;Change History: Created 6/22/87 DM ; ;Input: Fatal_Error = NO ; ;Output: Fatal_Error = YES/NO ; ;***************************************************************************** Procedure Parse_Command_Line ;AN000; push ds ;AN000; mov ds,psp_ptr ;AN000; ASSUME DS:NOTHING ;AN000; mov si,Command_Line_Parms ;AN000; mov ax,seg command_line_table ;AN000; push es ;AN000; mov es,ax ;AN000; ASSUME ES:NOTHING ;AN000; mov di,offset Command_Line_Table ;AN000; xor cx,cx ;AN000; PUBLIC MainParseLoop MainParseLoop: ; $DO ;AN000; $$DO7: xor dx,dx ;AN000; mov es:parse_ptr,si call Sysparse ;AN000; cmp ax,No_Error ;AN000; ; $IF E ;AN000; JNE $$IF8 ; Check if /? switch entered. ; If so, display the options help message ; and set for exit. ; ; This gives the user the info they want, ; without all the other possible error messages. ; ; 4/18/90 c-PaulB cmp es:[sw_synonym1], offset sw1_s1 ; /? jne CheckSW1Done ; skip this if not call DisplayOptions ; else display msg mov es:[Fatal_Error], YES ; set flag to stop jmp ParseCLExit ; and bail out now CheckSW1Done: push ax ;AN000; push bx ;AN000; push ds ;AN000; push es ;AN000; push si ;AN000; push di ;AN000; cmp cx,1 ;AN000; ; $IF E ;AN000; JNE $$IF9 mov ax,seg rb_string1_off ;AN000; mov ds,ax ;AN000; ASSUME DS:NOTHING ;AN000; mov si,offset rb_string1_off ;AN000; mov ax,ds:[si] ;AN000; mov bx,ax ;AN000; mov ax,ds:[si+2] ;AN000; mov ds,ax ;AN000; ASSUME DS:NOTHING ;AN000; mov si,bx ;AN000; mov ax,seg file1 ;AN000; mov es,ax ;AN000; ASSUME ES:NOTHING ;AN000; mov di,offset file1 ;AN000; call copyfs ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN9 $$IF9: mov ax,seg rb_string2_off ;AN000; mov ds,ax ;AN000; ASSUME DS:NOTHING ;AN000; mov si,offset rb_string2_off ;AN000; mov ax,ds:[si] ;AN000; mov bx,ax ;AN000; mov ax,ds:[si+2] ;AN000; mov ds,ax ;AN000; ASSUME DS:NOTHING ;AN000; mov si,bx ;AN000; mov ax,seg file2 ;AN000; mov es,ax ;AN000; ASSUME ES:NOTHING ;AN000; mov di,offset file2 ;AN000; call copyfs ;AN000; ; $ENDIF ;AN000; $$EN9: pop di ;AN000; pop si ;AN000; pop es ;AN000; ASSUME ES:NOTHING ;AN000; pop ds ;AN000; ASSUME DS:NOTHING ;AN000; pop bx ;AN000; pop ax ;AN000; ; $ENDIF ;AN000; $$IF8: cmp ax,No_Error ;AN000; ; $ENDDO NE ;AN000; JE $$DO7 cmp ax,End_of_Parse ;Check for parse error ;AN000; ; $IF NE ;AN000; JE $$IF14 push ax ;AN001; mov ax,es:parse_ptr ;AN001; mov es:parsoff,ax ;AN001; mov es:parseg,ds ;AN001; mov byte ptr ds:[si],0 ;AN001; pop ax ;AN001; parse_message ;Must enter file name ;AN000; mov es:Fatal_Error,YES ;Indicate death! ;AN000; ; $ENDIF ;AN000; $$IF14: ParseCLExit: pop es ;AN000; ASSUME ES:NOTHING ;AN000; pop ds ;AN000; ASSUME DS:DATA ;AN000; ret ;AN000; Parse_Command_Line endp ;AN000; ;***************************************************************************** ;Routine name: Parse_Command_Line ;***************************************************************************** ; ;Description: Displays options help message lines. ; ;Called Procedures: Display_Interface ; ;Change History: Created 5/2/90 c-PaulB ; ;Input: No value passed. ; ;Output: No value returned. ; ;***************************************************************************** Procedure DisplayOptions mov dx, offset msgOptions ; get options msg DO_Loop: call Display_Interface ; and show it cmp word ptr es:[msgOptions], MSG_OPTIONS_LAST ; last msg? je DO_Done ; done if so inc word ptr es:[msgOptions] ; else get next msg jmp short DO_Loop ; and go do it DO_Done: ret DisplayOptions endp ;***************************************************************************** INCLUDE PARSE.ASM ;***************************************************************************** procedure LOCATE near push ds ;AN000; ASSUME ES:NOTHING ; THIS IS THE WAY IT GETS HERE! ;AN000; mov ax,es ; ES -> PSP ;AN000; mov ds,ax ; DS -> PSP ;AN000; ASSUME DS:NOTHING ;AN000; MOV SI,offset file1 MOV BX,SEG DATA MOV ES,BX assume es:data ;AN000; MOV BX,WORD PTR DS:[2] ;Get size of memory ;-----------------------------------------------------------------------; ; ; The rules for the arguments are: ; File 1: ; If no extention is present, .EXE is used. ; File 2: ; If no drive is present in file2, use the one from file1 ; If no path is specified, then use current dir ; If no filename is specified, use the filename from file1 ; If no extention is present in file2, .BIN is used ; ;----- Get the first file name push ds ;AN000; push es ;AN000; ASSUME ES:DATA ;AN000; pop ds ;AN000; ASSUME DS:DATA ;AN000; sj01: mov si,offset file1 ; d = file1; mov per11,0 ; assume no extension on file1;AC000; ;****************************************************************************** sj0: lodsb ; while (!IsBlank(c=*p++)) { cmp al,0 JE SJ2 call dbcs_check ; see if a dbcs character ;AN000; jc dbcs_1 ; dbcs character, go load another char ;AN000; cmp al,'\' ; if (c == '\\' || c == ':') { jnz sj05 mov per11,update ;AC000; mov fnptr,si ; fnptr = ptr to slash sj05: cmp al,':' ; if (c == '\\' || c == ':') { jnz checkper1 mov per11,update ;AC000; mov fnptr,si ; fnptr = ptr to slash checkper1: cmp al,'.' ; if (c == '.') jne sj0 ; ;M001 mov per11,noupdate ; set file1 to have extension ;AN000; jmp short sj0 ; ;M001 ;M001 - code removed dbcs_1: ; ;AN000; lodsb ; load another character and got to ;AN000; jmp short sj0 ; the start again. ;AN000; ;****************************************************************************** sj2: get_second: ;----- Get the second file name ; Initially we assume that user has not given any file2 spec. Then if we find ; that user has entered something, then file2_given is made to TRUE; ; Once file2_given is TRUE, then we assume that user has given atleast a name ; i.e. name2_given = 1 but ext2_given = 0; ; if we find that user has given just a drive: then name2_given is made to FALSE ; The logic then simplifies to : ; if (!file2_given) ; copy file1 and add .BIN ext and try to open ; else { /* file2 given */ ; if (!name2_given) ; copy name from file1 and .BIN as extn ; try to open ; else { /* name2 also given */ ; do find_first ; if (file_not_found) ; add extn .BIN if needed and try to open ; else if (it is subdir) { ; add '\' to it; ; add the file1 name and .BIN ; go for file open ; } ; } /* else name2 given*/ ; } /* else file2 given */ MOV SI,offset file1 mov di,offset file2 ; d = file2 ;****************************************************************************** sj3: cmp word ptr [di],00 ; check to see if first character of je sj32 ; file2 is a null. ;AN000; mov file2_given,1 ; user has given atleast a partial ; spec for file2 mov si,offset file2 ; set pointer to file2 ;****************************************************************************** sj31: lodsb ; If file2 first character is not a mov f2cspot,si cmp al,0 ; null, this loop will check to see JZ maycopy ; the file has an extension assigned;AN000; call dbcs_check ; to it. If not it will set per2 to ;AN000; jc dbcs_2 ; go load another byte ;AN000; cmp al,'\' jnz checkper6 cmp byte ptr [si],0 ; end of file2 spec ? jne sj31 ; no, go get next char mov name2_given,0 ; copy from file1 checkper6: cmp al,':' ; if (c == '\\' || c == ':') { jnz checkper4 cmp byte ptr [si],0 ; end of file2 spec ? jne sj31 ; no, go get next char mov name2_given,0 ; no name; copy from file1 checkper4: ; there is an extension already. cmp al,'.' ; jne sj31 ; M001 mov ext2_given,1 ; M001 - code removed jmp short sj31 ; M001 ; M001 - code removed dbcs_2: ; lodsb ;load another character and got to ;AN000; jmp short sj31 ;the start again. ;AN000; ;****************************************************************************** ; we get here only if user specified something - a drive, just a name or ; even the full spec ; check if we have to copy the name maycopy: cmp name2_given,1 ; did the user give a name je sj5 ; yes, go check for the existence dec f2cspot mov di,f2cspot sj32: ; There is no second filename so mov si,fnptr ;AN000; ;****************************************************************************** copy1to2: ;AN000; lodsb ; This loop is executed when there is ;AN000; cmp al,0 ; no file2 specified on the command ;AN000; JZ SJ5 ; line. It will copy the file1 name ;AN000; call dbcs_check ; check for dbcs character ;AN000; jc dbcs_3 ; got a dbcs character, go copy. ;AN000; cmp al,'.' ; extension. The defult extension ;AN000; je sj5 ; of .BIN will be added in check_ext. ;AN000; stosb ;AN000; jmp short copy1to2 ;AN000; dbcs_3: stosb ; Got a dbcs character. Copy ;AN000; lodsb ; two characters and then go to ;AN000; stosb ; next character in filename. ;AN000; jmp short copy1to2 ;AN000; ;AN000; ;****************************************************************************** sj5: ; mov byte ptr es:[di],00h ; *d = 0; cmp file2_given,1 ; if the user specified some path jne check_ext ; we need to check it; else cmp name2_given,1 ; add .BIN and try to open file2 jne check_ext ; (at this point we have the name) mov ah,Set_DMA ; Use find_first to see if file2 is mov dx,offset dma_buf ; a directory. If it isn't, go to int 21h ; set f2cspot to point to the spot mov ah,Find_First ; right after the backslash, and mov dx,offset file2 ; fall through to no_second so that mov cx,-1 ; file1's name will be added to file2. int 21h jc check_ext test dma_buf+21,00010000b jNZ DoDirectory jmp short Check_Ext DoDirectory: mov AL,'\' mov di,f2cspot dec di stosb inc f2cspot mov name2_given,0 ; so that we will copy file1.ext to mov ext2_given,0 ; file2; we also have to copy ext jmp maycopy ; ;----- Check that files have an extension, otherwise set default check_ext: cmp per11,noupdate ; if (ext2_given == NULL) { ;AC000; jz file1_ok mov di,offset file1 ; d = file1; mov si,offset file1_ext ; s = ".EXE"; call strcat ; strcat (d, s); file1_ok: ; } cmp ext2_given,1 ; if (ext2_given == NULL) { ;AC000; je file2_ok mov di,offset file2 ; d = file2; mov si,offset file2_ext ; s = ".BIN"; call strcat ; strcat (d, s); jmp short file2_ok ; } ;-----------------------------------------------------------------------; file2_ok: mov dx,offset file1 mov ax,(open SHL 8) + 0 ;for reading only INT 21H ;Open input file jc bad_file mov [handle1],ax jmp short exeload bad_file: jmp DosError BADEXE: pop ds ASSUME DS:nothing ;AN000; MESSAGE msgNoConvert ;AC000; jmp getout ;AN000; ReadError: jmp DosError EXELOAD: ASSUME DS:DATA ;AN000; MOV DX,OFFSET RUNVAR ;Read header in here MOV CX,RUNVARSIZ ;Amount of header info we need push bx mov bx,[handle1] MOV AH,read INT 21H ;Read in header pop bx jc ReadError CMP [RELPT],5A4DH ;Check signature word JNZ BADEXE MOV AX,[HEADSIZ] ;size of header in paragraphs ADD AX,31 ;Round up first CMP AX,1000H ;Must not be >=64K JAE TOOBIG AND AX,NOT 31 MOV CL,4 SHL AX,CL ;Header size in bytes push dx push cx push ax push bx mov dx,ax xor cx,cx mov al,0 mov bx,[handle1] mov ah,lseek int 21h jc LseekError pop bx pop ax pop cx pop dx XCHG AL,AH SHR AX,1 ;Convert to pages MOV DX,[PAGES] ;Total size of file in 512-byte pages SUB DX,AX ;Size of program in pages CMP DX,80H ;Fit in 64K? (128 * 512 = 64k) JAE TOOBIG XCHG DH,DL SHL DX,1 ;Convert pages to bytes MOV AX,[LASTP] ;Get count of bytes in last page OR AX,AX ;If zero, use all of last page JZ WHOLEP IF OLDLINK CMP AX,4 ;Produced by old linker? JZ WHOLEP ;If so, use all of last page too ENDIF SUB DX,200H ;Subtract last page ADD DX,AX ;Add in byte count for last page WHOLEP: MOV [SIZ],DX ADD DX,15 SHR DX,CL ;Convert bytes to paragraphs MOV BP,SEG LOAD ADD DX,BP ;Size + start = minimum memory (paragr.) CMP DX,BX ;Enough memory? JA TOOBIG MOV AX,[INITSS] OR AX,[INITSP] OR AX,[INITCS] JMP short ERRORNZ TOOBIG: pop ds ASSUME DS:NOTHING ;AN000; MESSAGE msgOutOfMemory ;AN000; jmp getout ;AN000; LseekError: jmp DosError ERRORNZ: ASSUME DS:DATA ;AN000; jz xj JMP BADEXE ;AC000; For ptm P475; xj: MOV AX,[INITIP] OR AX,AX ;If IP=0, do binary fix JZ BINFIX CMP AX,100H ;COM file must be set up for CS:100 JNZ ERRORNZ push dx push cx push ax push bx mov dx,100h ;chop off first 100h xor cx,cx mov al,1 ;seek from current position mov bx,[handle1] mov ah,lseek int 21h jc LseekError pop bx pop ax pop cx pop dx SUB [SIZ],AX ;And count decreased size CMP [RELCNT],0 ;Must have no fixups JNZ ERRORNZ BINFIX: XOR BX,BX ;Initialize fixup segment ;See if segment fixups needed CMP [RELCNT],0 JZ LOADEXE GETSEG: pop ds ASSUME DS:NOTHING ;AN000; MESSAGE msgFixUp ;AN000; PUSH DS PUSH ES POP DS ASSUME DS:DATA ;AN000; MOV AH,STD_CON_STRING_INPUT MOV DX,OFFSET INBUF INT 21H ;Get user response MOV SI,OFFSET INBUF+2 ;;dcl;; MOV BYTE PTR [SI-1],0 ;Any digits? cmp BYTE PTR [SI-1],0 ;Any digits? ;AC000; JZ GETSEG DIGLP: LODSB SUB AL,"0" JC DIGERR CMP AL,10 JB HAVDIG AND AL,5FH ;Convert to upper case SUB AL,7 CMP AL,10 JB DIGERR CMP AL,10H JAE DIGERR HAVDIG: SHL BX,1 SHL BX,1 SHL BX,1 SHL BX,1 OR BL,AL JMP DIGLP DIGERR: CMP BYTE PTR [SI-1],0DH ;Is last char. a CR? JNZ GETSEG LOADEXE: XCHG BX,BP ;BX has LOAD, BP has fixup MOV CX,[SIZ] MOV AH,read push di mov di,[handle1] PUSH DS MOV DS,BX ASSUME DS:NOTHING ;AN000; XOR DX,DX push bx mov bx,di INT 21H ;Read in up to 64K pop bx POP DS ASSUME DS:DATA ;AN000; pop di Jnc HAVEXE ;Did we get it all? jmp DosError LseekError2: jmp DosError HAVEXE: ASSUME DS:DATA ;AN000; CMP [RELCNT],0 ;Any fixups to do? JZ STORE MOV AX,[RELTAB] ;Get position of table push dx push cx push ax push bx mov dx,ax xor cx,cx mov al,0 mov bx,[handle1] mov ah,lseek int 21h jc LseekError2 pop bx pop ax pop cx pop dx MOV DX,OFFSET RELPT ;4-byte buffer for relocation address RELOC: MOV DX,OFFSET RELPT ;4-byte buffer for relocation address MOV CX,4 MOV AH,read push bx mov bx,[handle1] INT 21H ;Read in one relocation pointer pop bx Jnc RDCMP jmp short DosError RDCMP: MOV DI,[RELPT] ;Get offset of relocation pointer MOV AX,[RELSEG] ;Get segment ADD AX,BX ;Bias segment with actual load segment MOV ES,AX ASSUME ES:NOTHING ;AN000; ADD ES:[DI],BP ;Relocate DEC [RELCNT] ;Count off JNZ RELOC STORE: MOV AH,CREAT MOV DX,OFFSET file2 xor cx,cx INT 21H Jc MKERR mov [handle2],ax MOV CX,[SIZ] MOV AH,write push di mov di,[handle2] PUSH DS MOV DS,BX ASSUME DS:NOTHING ;AN000; XOR DX,DX ;Address 0 in segment push bx mov bx,di INT 21H pop bx POP DS ASSUME DS:DATA ;AN000; pop di Jc WRTERR ;Must be zero if more to come cmp AX,CX jnz NOROOM MOV AH,CLOSE push bx mov bx,[handle2] INT 21H jc CloseError pop bx pop ds pop ds ASSUME DS:NOTHING ;AN000; RET ;******************************************************************************* NOROOM: ; ;AN000; ASSUME DS:DATA ;AN000; MOV AH,CLOSE ; Close the file here ;AN000; push bx ; ;AN000; mov bx,[handle2] ; ;AN000; INT 21H ; ;AN000; jc CloseError ; If error let extend messages get it;AN000; pop bx ; ;AN000; mov ah,UNLINK ; Delete the file because it did ;AN000; MOV DX,OFFSET file2 ; not get written correctly. ;AN000; INT 21H ; ;AN000; jc CloseError ; If error let extend messages get it;AN000; pop ds ; ;AN000; ASSUME DS:NOTHING ; ;AN000; message msgNoDiskSpace ; Put out insufficient disk space ;AN000; jmp short getout ; message ;AN000; RET ; return to main_init ;AN000; ;******************************************************************************* WRTERR: ;AN000; MKERR: ;AN000; CloseError: ;AN000; public DosError ;AN000; DosError: ;AN000; mov es:FileNameSegment,ds ; save for opens, creates, ;AN000; mov es:FileNameOffset,dx ;AN000; mov bx,0 ; get the extended error code ;AN000; mov ah,059h ;AN000; int 21h ;AN000; mov si,offset ds:Sublist_msg_exterror ;AC001; extend_message ;AN001; pop ds ;AN001; getout: ;AN000; pop ds ;AN000; ASSUME DS:NOTHING ;AN000; ret ;AN000; LOCATE ENDP ;----- concatenate two strings strcat proc near ; while (*d) cmp byte ptr [di],0 jz atend inc di ; d++; jmp strcat atend: ; while (*d++ = *s++) lodsb stosb or al,al ; ; jnz atend ret strcat endp ;----- Find the first non-ignorable char, return carry if CR found kill_bl proc near cld sj10: ; while ( *p != 13 && lodsb CMP AL,13 ; IsBlank (*p++)) JZ BreakOut CALL IsBlank JZ SJ10 ; ; BreakOut: dec si ; p--; cmp al,0dh ; return *p == 13; clc jne sj11 stc sj11: ret kill_bl endp IsBlank proc near cmp al,00 ;AN000; retz ;AN000; cmp al,13 retz cmp al,' ' ; space retz cmp al,9 ; tab retz cmp al,',' ; comma retz cmp al,';' ; semicolon retz cmp al,'+' ; plus retz cmp al,10 ; line feed retz cmp al,'=' ; equal sign return IsBlank Endp procedure copyfs near push ax ;AN000; ; $do ; while we have filespec ;AN000; $$DO16: lodsb ; move byte to al ;AN000; cmp al,0 ; see if we are at ;AN000; ; the end of the ; filespec ; $leave e ; exit while loop ;AN000; JE $$EN16 stosb ; move byte to path_name ;AN000; ; $enddo ; end do while ;AN000; JMP SHORT $$DO16 $$EN16: stosb ;AN000; pop ax ;AN000; ret ;AN000; copyfs endp ;AN000; procedure dbcs_check near push ds ;Save registers ;AC000; push si ; " " " " ;AC000; push ax ; " " " " ;AC000; push ds ; " " " " ;AC000; pop es ;Establish addressability;AC000; cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;AC000; push ax ;Save input character ;AC000; ; $IF NE ;Nope ;AN000; JE $$IF19 mov al,0 ;Get DBCS environment vectors;AC000; DOS_Call Hongeul ; " " " " ;AC000; mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector;AC000; mov es:DBCS_Vector_Off,si ;Save the vector ;AC000; mov ax,ds ; ;AC000; mov es:DBCS_Vector_Seg,ax ; ;AC000; ; $ENDIF ; for next time in ;AC000; $$IF19: pop ax ;Restore input character;AC000; mov si,es:DBCS_Vector_Seg ;Get saved vector pointer;AC000; mov ds,si ; ;AC000; mov si,es:DBCS_Vector_Off ; ;AC000; ; $SEARCH ;Check all the vectors ;AC000; $$DO21: cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;AC000; ; $LEAVE E ;Yes, done ;AC000; JE $$EN21 cmp al,ds:[si] ;See if char is in vector;AC000; ; $EXITIF AE,AND ;If >= to lower, and ;AC000; JNAE $$IF21 cmp al,ds:[si+1] ; =< than higher range ;AC000; ; $EXITIF BE ; then DBCS character ;AC000; JNBE $$IF21 stc ;Set CY to indicate DBCS;AC000; ; $ORELSE ;Not in range, check next;AC000; JMP SHORT $$SR21 $$IF21: add si,DBCS_Vector_Size ;Get next DBCS vector ;AC000; ; $ENDLOOP ;We didn't find DBCS chaR;AC000; JMP SHORT $$DO21 $$EN21: clc ;Clear CY for exit ;AC000; ; $ENDSRCH ; ;AC000; $$SR21: pop ax ;Restore registers ;AC000; pop si ; " " " " ;AC000; pop ds ;Restore data segment ;AC000; ret ; ;AC000; ret ;AN000; dbcs_check endp ;AN000; CODE ends end main_init ;AC000;