summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/EXE2BIN/LOCATE.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/EXE2BIN/LOCATE.ASM')
-rw-r--r--v4.0/src/CMD/EXE2BIN/LOCATE.ASM592
1 files changed, 592 insertions, 0 deletions
diff --git a/v4.0/src/CMD/EXE2BIN/LOCATE.ASM b/v4.0/src/CMD/EXE2BIN/LOCATE.ASM
new file mode 100644
index 0000000..a2d44f4
--- /dev/null
+++ b/v4.0/src/CMD/EXE2BIN/LOCATE.ASM
@@ -0,0 +1,592 @@
1; SCCSID = @(#)locate.asm 4.3 85/09/13
2Title LOCATE (EXE2BIN)
3
4; Loader for EXE files under 86-DOS
5; VER 1.5
6; 05/21/82 Added rev number
7; VER 1.6
8; 07/01/82 A little less choosy about size matches
9; VER 2.0 M.A.U
10; 10/08/82 Modified to use new 2.0 system calls for file i/o
11; Ver 2.1 M.A.U
12; 10/27/82 Added the DOS version check
13; Ver 2.2 MZ
14; 8/30/83 Fixed command line parsing
15; Ver 2.3 EE
16; 10-12-83 More fixes to command line parsing
17; Ver 2.4 NP
18; 10/17/83 Use Printf for messages
19; Ver 2.5 MZ Fix LOCATE sss D: problem
20; 04/09/87 Add PARSER and MESSAGE RETRIEVER
21; Ver 4.00 DRM
22
23; The following switch allows use with the "old linker", which put a version
24; number where the new linker puts the number of bytes used in the last page.
25; If enabled, this will cause a test for 0004 at this location (the old linker
26; version number), and if equal, change it to 200H so all of the last page
27; will be used.
28
29
30OLDLINK EQU 0 ;1 to enable, 0 to disable
31
32 .xlist
33
34; INCLUDE DOSSYM.INC ; also versiona.inc
35; INCLUDE E2BMACRO.INC
36
37 .list
38
39 subttl Main Code Area
40 page
41
42DATA SEGMENT PUBLIC BYTE
43
44rev db "2.4"
45
46
47file1_ext db ".EXE",00h
48file2_ext db ".BIN",00h
49
50per1 dW 0
51per2 db 0
52
53file1 db (64+13) dup(?)
54fnptr dw offset file1 ; Ptr to filename in file1
55handle1 dw 1 dup(?)
56
57file2 db (64+13) dup(?)
58f2cspot dw offset file2 ; Ptr to spot in file2, file1 maybe added
59handle2 dw 1 dup(?)
60
61dma_buf db 80h dup(0) ; DMA transfer buffer
62
63INBUF DB 5,0
64 DB 5 DUP(?)
65
66;The following locations must be defined for storing the header:
67
68RUNVAR LABEL BYTE ;Start of RUN variables
69RELPT DW ?
70LASTP LABEL WORD
71RELSEG DW ?
72SIZ LABEL WORD ;Share these locations
73PAGES DW ?
74RELCNT DW ?
75HEADSIZ DW ?
76 DW ?
77LOADLOW DW ?
78INITSS DW ?
79INITSP DW ?
80 DW ?
81INITIP DW ?
82INITCS DW ?
83RELTAB DW ?
84RUNVARSIZ EQU $-RUNVAR
85
86DATA ENDS
87
88STACK SEGMENT WORD STACK
89 DB (362 - 80h) + 80H DUP (?) ; (362 - 80h) is IBMs ROM requirement
90 ; (New - Old) == size of growth
91STACK ENDS
92
93
94ZLOAD SEGMENT
95ZLOAD ENDS
96LOAD EQU ZLOAD
97
98
99CODE SEGMENT BYTE
100
101 ASSUME CS:CODE,SS:STACK
102
103LOCATE PROC NEAR
104
105LOCSTRT:
106 PUSH DS
107 XOR AX,AX
108 PUSH AX ;Push return address to DS:0
109
110
111 MOV SI,81H
112 MOV BX,DATA
113 MOV ES,BX
114 MOV BX,WORD PTR DS:[2] ;Get size of memory
115
116 assume es:data
117
118
119
120
121
122
123;-----------------------------------------------------------------------;
124
125;
126; The rules for the arguments are:
127; File 1:
128; If no extention is present, .EXE is used.
129; File 2:
130; If no drive is present in file2, use the one from file1
131; If no path is specified, then use current dir
132; If no filename is specified, use the filename from file1
133; If no extention is present in file2, .BIN is used
134;
135
136
137;----- Get the first file name
138 call kill_bl ; p = skipblanks (p);
139 jnc sj01 ; if (p == NULL)
140 push es
141 pop ds
142 MESSAGE msgNoFile ;AC000;
143sj01:
144 mov di,offset file1 ; d = file1;
145sj0:
146 lodsb ; while (!IsBlank(c=*p++)) {
147 CALL IsBlank
148 JZ SJ2
149 mov DX,per1
150 cmp al,'\' ; if (c == '\\' || c == ':') {
151 jz sj05
152 cmp al,':'
153 jnz checkper1
154sj05:
155 mov fnptr,di ; fnptr = ptr to slash
156 inc fnptr ; fnptr advanced past slash to fname
157 xor DX,DX ; per1 = NULL;
158checkper1:
159 cmp al,'.' ; if (c == '.')
160 jne sj1
161 mov DX,DI ; per1 = p-1;
162 DEC DX ;
163sj1:
164 mov per1,DX
165 stosb ; *d++ = c;
166 jmp short sj0 ; }
167sj2:
168 dec si ; p--;
169 mov byte ptr es:[di],00h ; *d = 0;
170 call kill_bl ; if (End(p))
171 jnc get_second
172 cmp byte ptr [file1+1],':' ; Drive spec on first file?
173 jnz nsja ; no
174 mov ax,word ptr file1 ; get drive stuff
175 mov word ptr file2,ax
176 inc f2cspot
177 inc f2cspot
178nsja:
179 jmp no_second ; goto No_second;
180
181
182get_second:
183;----- Get the second file name
184 mov di,offset file2 ; d = file2
185 cmp byte ptr [si+1],':' ; Drive spec on second file?
186 jz sj3 ; yes
187 cmp byte ptr [file1+1],':' ; Drive spec on first file?
188 jnz sj3 ; no
189 push ax ; Suck drive spec from file1
190 mov ax,word ptr file1
191 stosw
192 mov f2cspot,di
193 pop ax
194sj3:
195 lodsb ; while (!IsBlank(c=*p++)) {
196 CALL IsBlank
197 JZ SJ5
198 mov ah,per2
199 cmp al,'\' ; if (c == '\\')
200 jnz checkper2
201 xor ah,ah ; per2 = FALSE;
202checkper2:
203 cmp al,'.' ; if (c == '.')
204 jne sj4
205 mov ah,-1 ; per2 = TRUE;
206sj4:
207 mov per2,ah
208 stosb ; *d++ = c;
209 jmp short sj3 ; }
210sj5:
211 mov byte ptr es:[di],00h ; *d = 0;
212 mov ah,Set_DMA ; Use find_first to see if file2 is
213 mov dx,offset dma_buf ; a directory. If it isn't, go to
214 push es ; chex_ext. If it is, put a back-
215 pop ds ; slash on the end of the string,
216 int 21h ; set f2cspot to point to the spot
217 mov ah,Find_First ; right after the backslash, and
218 mov dx,offset file2 ; fall through to no_second so that
219 mov cx,-1 ; file1's name will be added to file2.
220 int 21h
221 jc checkDrive
222 test dma_buf+21,00010000b
223 jNZ DoDirectory
224 jmp Check_Ext
225CheckDrive:
226 CMP BYTE PTR ES:[DI-1],':'
227 JNZ Check_Ext ; if char is not a : then skip
228 JMP SetSecond ; presume drive:
229DoDirectory:
230 mov AL,5ch
231 stosb
232SetSecond:
233 mov per2,FALSE
234 mov f2cspot,di
235
236;----- Copy file1 to file2
237no_second:
238 PUSH ES
239 POP DS
240 assume ds:data
241
242 mov si,fnptr ; s = ptr to fname in file1;
243 mov di,f2cspot ; d = spot in file2 to cat file1;
244 mov dx,per1 ; dx = ptr to ext dot in file1;
245 inc dx
246
247sj6: ; while (TRUE) {
248 cmp SI,dx ; if (s == per1)
249 je sj7 ; break;
250 lodsb ; c = *s++;
251 cmp al,00h ; if (!c)
252 je sj7 ; break;
253 stosb ; *d++ = c;
254 jmp short sj6 ; }
255sj7:
256 mov byte ptr [di],00h ; *d = 0;
257
258;----- Check that files have an extension, otherwise set default
259check_ext:
260 PUSH ES
261 POP DS
262 assume ds:data
263
264 cmp per1,0 ; if (per1 == NULL) {
265 jNZ file1_ok
266 mov di,offset file1 ; d = file1;
267 mov si,offset file1_ext ; s = ".EXE";
268 call strcat ; strcat (d, s);
269file1_ok: ; }
270 cmp per2,-1 ; if (per2 != NULL) {
271 je file2_ok
272 mov di,offset file2 ; d = file2;
273 mov si,offset file2_ext ; s = ".BIN";
274 call strcat ; strcap (d, s);
275 jmp short file2_ok ; }
276
277;-----------------------------------------------------------------------;
278file2_ok:
279 mov dx,offset file1
280 mov ax,(open SHL 8) + 0 ;for reading only
281 INT 21H ;Open input file
282 jc bad_file
283 mov [handle1],ax
284 jmp exeload
285
286bad_file:
287 MESSAGE msgNoFile ;AC000;
288 call TriageError
289BADEXE:
290 MESSAGE msgNoConvert ;AC000;
291TOOBIG:
292 MESSAGE msgOutOfMemory ;AC000;
293
294EXELOAD:
295 MOV DX,OFFSET RUNVAR ;Read header in here
296 MOV CX,RUNVARSIZ ;Amount of header info we need
297 push bx
298 mov bx,[handle1]
299 MOV AH,read
300 INT 21H ;Read in header
301 pop bx
302 CMP [RELPT],5A4DH ;Check signature word
303 JNZ BADEXE
304 MOV AX,[HEADSIZ] ;size of header in paragraphs
305 ADD AX,31 ;Round up first
306 CMP AX,1000H ;Must not be >=64K
307 JAE TOOBIG
308 AND AX,NOT 31
309 MOV CL,4
310 SHL AX,CL ;Header size in bytes
311
312 push dx
313 push cx
314 push ax
315 push bx
316 mov dx,ax
317 xor cx,cx
318 mov al,0
319 mov bx,[handle1]
320 mov ah,lseek
321 int 21h
322 pop bx
323 pop ax
324 pop cx
325 pop dx
326
327 XCHG AL,AH
328 SHR AX,1 ;Convert to pages
329 MOV DX,[PAGES] ;Total size of file in 512-byte pages
330 SUB DX,AX ;Size of program in pages
331 CMP DX,80H ;Fit in 64K?
332 JAE TOOBIG
333 XCHG DH,DL
334 SHL DX,1 ;Convert pages to bytes
335 MOV AX,[LASTP] ;Get count of bytes in last page
336 OR AX,AX ;If zero, use all of last page
337 JZ WHOLEP
338
339 IF OLDLINK
340 CMP AX,4 ;Produced by old linker?
341 JZ WHOLEP ;If so, use all of last page too
342 ENDIF
343
344 SUB DX,200H ;Subtract last page
345 ADD DX,AX ;Add in byte count for last page
346WHOLEP:
347 MOV [SIZ],DX
348 ADD DX,15
349 SHR DX,CL ;Convert bytes to paragraphs
350 MOV BP,LOAD
351 ADD DX,BP ;Size + start = minimum memory (paragr.)
352 CMP DX,BX ;Enough memory?
353 JA TOOBIG
354 MESSAGE msgNoConvert ;AC000;
355 MOV AX,[INITSS]
356 OR AX,[INITSP]
357 OR AX,[INITCS]
358ERRORNZ:
359 jz xj
360 JMP WRTERR ;Must not have SS, SP, or CS to init.
361xj: MOV AX,[INITIP]
362 OR AX,AX ;If IP=0, do binary fix
363 JZ BINFIX
364 CMP AX,100H ;COM file must be set up for CS:100
365 JNZ ERRORNZ
366
367 push dx
368 push cx
369 push ax
370 push bx
371 mov dx,100h ;chop off first 100h
372 xor cx,cx
373 mov al,1 ;seek from current position
374 mov bx,[handle1]
375 mov ah,lseek
376 int 21h
377 pop bx
378 pop ax
379 pop cx
380 pop dx
381
382 SUB [SIZ],AX ;And count decreased size
383 CMP [RELCNT],0 ;Must have no fixups
384 JNZ ERRORNZ
385BINFIX:
386 XOR BX,BX ;Initialize fixup segment
387;See if segment fixups needed
388 CMP [RELCNT],0
389 JZ LOADEXE
390GETSEG:
391 MESSAGE msgFixUp ;AC000;
392 MOV AH,STD_CON_STRING_INPUT
393 MOV DX,OFFSET INBUF
394 INT 21H ;Get user response
395 MOV SI,OFFSET INBUF+2
396 MOV BYTE PTR [SI-1],0 ;Any digits?
397 JZ GETSEG
398DIGLP:
399 LODSB
400 SUB AL,"0"
401 JC DIGERR
402 CMP AL,10
403 JB HAVDIG
404 AND AL,5FH ;Convert to upper case
405 SUB AL,7
406 CMP AL,10
407 JB DIGERR
408 CMP AL,10H
409 JAE DIGERR
410HAVDIG:
411 SHL BX,1
412 SHL BX,1
413 SHL BX,1
414 SHL BX,1
415 OR BL,AL
416 JMP DIGLP
417
418DIGERR:
419 CMP BYTE PTR [SI-1],0DH ;Is last char. a CR?
420 JNZ GETSEG
421LOADEXE:
422 XCHG BX,BP ;BX has LOAD, BP has fixup
423
424 MOV CX,[SIZ]
425 MOV AH,read
426 push di
427 mov di,[handle1]
428 PUSH DS
429 MOV DS,BX
430 XOR DX,DX
431 push bx
432 mov bx,di
433 INT 21H ;Read in up to 64K
434 pop bx
435 POP DS
436 pop di
437 Jnc HAVEXE ;Did we get it all?
438 MESSAGE msgReadError ;AC000;
439HAVEXE:
440 CMP [RELCNT],0 ;Any fixups to do?
441 JZ STORE
442 MOV AX,[RELTAB] ;Get position of table
443
444 push dx
445 push cx
446 push ax
447 push bx
448 mov dx,ax
449 xor cx,cx
450 mov al,0
451 mov bx,[handle1]
452 mov ah,lseek
453 int 21h
454 pop bx
455 pop ax
456 pop cx
457 pop dx
458
459 MOV DX,OFFSET RELPT ;4-byte buffer for relocation address
460RELOC:
461 MOV DX,OFFSET RELPT ;4-byte buffer for relocation address
462 MOV CX,4
463 MOV AH,read
464 push bx
465 mov bx,[handle1]
466 INT 21H ;Read in one relocation pointer
467 pop bx
468 Jnc RDCMP
469 JMP BADEXE
470RDCMP:
471 MOV DI,[RELPT] ;Get offset of relocation pointer
472 MOV AX,[RELSEG] ;Get segment
473 ADD AX,BX ;Bias segment with actual load segment
474 MOV ES,AX
475 ADD ES:[DI],BP ;Relocate
476 DEC [RELCNT] ;Count off
477 JNZ RELOC
478STORE:
479 MOV AH,CREAT
480 MOV DX,OFFSET file2
481 xor cx,cx
482 INT 21H
483 Jc MKERR
484 mov [handle2],ax
485 MOV CX,[SIZ]
486 MOV AH,write
487 push di
488 mov di,[handle2]
489 PUSH DS
490 MOV DS,BX
491 XOR DX,DX ;Address 0 in segment
492 push bx
493 mov bx,di
494 INT 21H
495 pop bx
496 POP DS
497 pop di
498 Jc WRTERR ;Must be zero if more to come
499 MOV AH,CLOSE
500 push bx
501 mov bx,[handle2]
502 INT 21H
503 pop bx
504 RET
505
506WRTERR:
507 MESSAGE msgOutOfMemory ;AC000;
508
509MKERR:
510 MESSAGE msgFileCreateError ;AC000;
511 Call TriageError
512
513
514LOCATE ENDP
515
516;----- concatenate two strings
517strcat proc near ; while (*d)
518 cmp byte ptr [di],0
519 jz atend
520 inc di ; d++;
521 jmp strcat
522atend: ; while (*d++ = *s++)
523 lodsb
524 stosb
525 or al,al ; ;
526 jnz atend
527 ret
528strcat endp
529
530;----- Find the first non-ignorable char, return carry if CR found
531kill_bl proc near
532 cld
533sj10: ; while ( *p != 13 &&
534 lodsb
535 CMP AL,13 ; IsBlank (*p++))
536 JZ BreakOut
537 CALL IsBlank
538 JZ SJ10 ; ;
539BreakOut:
540 dec si ; p--;
541 cmp al,0dh ; return *p == 13;
542 clc
543 jne sj11
544 stc
545sj11:
546 ret
547kill_bl endp
548
549IsBlank proc near
550 cmp al,13
551 retz
552 cmp al,' ' ; space
553 retz
554 cmp al,9 ; tab
555 retz
556 cmp al,',' ; comma
557 retz
558 cmp al,';' ; semicolon
559 retz
560 cmp al,'+' ; plus
561 retz
562 cmp al,10 ; line feed
563 retz
564 cmp al,'=' ; equal sign
565 return
566IsBlank Endp
567
568;
569; Take a default message pointer in DX and convert it to access-denied iff
570; the extended error indicates so. Leave all other registers (except AX)
571; alone.
572;
573Procedure TriageError,near
574 retnc ; no carry => do nothing...
575 PUSHF
576 SaveReg <BX,CX,SI,DI,BP,ES,DS,AX,DX>
577 MOV AH,GetExtendedError
578 INT 21h
579 RestoreReg <CX,BX> ; restore original AX
580 MESSAGE msgNoAccess ;AC000;
581 CMP AX,65 ; network access denied?
582 JZ NoMove ; Yes, return it.
583 MOV AX,BX
584 MOV DX,CX
585NoMove:
586 RestoreReg <DS,ES,BP,DI,SI,CX,BX>
587 popf
588 return
589TriageError ENDP
590
591CODE ENDS
592 END LOCATE