|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 39936 (0x9c00) Types: TextFile Names: »STARTUP.A86«
└─⟦fa5b86546⟧ Bits:30002725 SW1609 Digital Research C - CCP/M - Oct 83 └─ ⟦this⟧ »STARTUP.A86«
; This startup file is actually several files edited together: ; clear.a86, startup.a86, minitsta.a86, minitcmd.a86, minitrel.a86, ; minithea.a86, miniterr.a86. The include statements and public/extrn ; statements that connect the separate files have been commented out. ; ; The first file, clear.a86, provides the definitions that make model ; independent coding possible. ; C32 equ 0 ; Small code model (use 1 for big model) D32 equ 0 ; Small data model (use 1 for big model) nolist ; ; Stack Frame Offsets ; if C32 ;-------------------------------------------------------------- if D32 ;------------------------------------------------------------ ; ARG1 equ 8 ; Offset from ÆBPÅ of caller argument #1 ; ; RAseg equ 6 ; Offset from ÆBPÅ of caller return address segment ; ; RAoff equ 4 ; Offset from ÆBPÅ of caller return address offset ; ; SAVEDS equ 2 ; Offset from ÆBPÅ of caller DS slot ; ; else ;-----------------------------------------------------------; ; ARG1 equ 6 ; Offset from ÆBPÅ of caller argument #1 ; ; RAseg equ 4 ; Offset from ÆBPÅ of caller return address segment ; ; RAoff equ 2 ; Offset from ÆBPÅ of caller return address offset ; ; endif ;------------------------------------------------------------ ; else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; if D32 ;------------------------------------------------------------ ; ARG1 equ 6 ; Offset from ÆBPÅ of caller argument #1 ; ; RAoff equ 4 ; Offset from ÆBPÅ of caller return address offset ; ; SAVEDS equ 2 ; Offset from ÆBPÅ of caller DS slot ; ; else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; ARG1 equ 4 ; Offset from ÆBPÅ of caller argument #1 ; ; RAoff equ 2 ; Offset from ÆBPÅ of caller return address offset ; ; endif ;-----------------------------------------------------------; ; endif ;-------------------------------------------------------------- SAVEBP equ 0 ; Offset from ÆBPÅ of caller BP slot SAVESP equ -2 ; Offset from ÆBPÅ of my own SP slot OVRAseg equ -4 ; Offset from ÆBPÅ of my own true return address segment OVRAoff equ -6 ; Offset from ÆBPÅ of my own true return address offset OVIDoff equ -8 ; Offset from ÆBPÅ of my own overlay index TEMP8 equ -16 ; Offset from ÆBPÅ of my 8 byte temporary DISPLAY equ -18 ; Offset from ÆBPÅ of my lexical father frame ONLINK equ -20 ; Offset from ÆBPÅ of the previous on-frame ONHEAD equ -22 ; Offset from ÆBPÅ of the first on-unit for this frame eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m o v e b y t e s / p a d b y t e s * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; codemacro MOVEBYTES db 0d1h ; shr cx,1 db 0e9h db 073h ; jnc even db 001h db 0a4h ; movsb db 0f3h ; even: rep movsw db 0a5h endm ; codemacro PADBYTES db 0d1h ; shr cx,1 db 0e9h db 073h ; jnc even db 001h db 0aah ; stosb db 0f3h ; even: rep stosw db 0abh endm ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * p o p r e g s / p u s h r e g s * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; codemacro POPREGS db 007h ; pop es db 05fh ; pop di db 05eh ; pop si db 05ah ; pop dx db 059h ; pop cx db 05bh ; pop bx db 058h ; pop ax db 05dh ; pop bp db 01fh ; pop ds endm ; codemacro PUSHREGS db 01eh ; push ds db 055h ; push bp db 08bh ; mov bp,sp db 0ech db 050h ; push ax db 053h ; push bx db 051h ; push cx db 052h ; push dx db 056h ; push si db 057h ; push di db 006h ; push es endm eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * p o p c / p u s h c / r e t c * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; if C32 ;-------------------------------------------------------------- ; CALLC equ CALLF JMPC equ JMPF POPC equ POP PUSHC equ PUSH RETC equ RETF ; else ; CALLC equ CALL JMPC equ JMP codemacro POPC dst:Ew endm codemacro POPC dst:S(ES) endm codemacro POPC dst:S(SS,DS) endm codemacro POPC dst:Rw endm codemacro PUSHC src:Ew endm codemacro PUSHC src:S endm codemacro PUSHC src:Rw endm RETC equ RET ; endif ;-------------------------------------------------------------- ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * l d x / l e x / p o p d / p u s h d * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; if D32 ;-------------------------------------------------------------- ; LDX equ LDS LEX equ LES POPD equ POP PUSHD equ PUSH ; else ; LDX equ MOV LEX equ MOV codemacro POPD dst:Ew endm codemacro POPD dst:S(ES) endm codemacro POPD dst:S(SS,DS) endm codemacro POPD dst:Rw endm codemacro PUSHD src:Ew endm codemacro PUSHD src:S endm codemacro PUSHD src:Rw endm ; endif ;-------------------------------------------------------------- list Name 'STARTUP' Title 'STARTUP' Pagesize 75 ; ; File name: STARTUP.A86 ; ; Module name: STARTUP ; ; Entry parameters: None. ; ; Return value: None. ; ; Entry point Arguments Function ; ----------- --------- -------- ; m.init None. Initialize the Common Language ; Environment and Runtime (CLEAR). ; ; Algorithm: Initialize the stack. ; Initialize the command name. ; Relocate the segment references if O/S has not. ; Initialize the heap. ; Address the command tail and call _main. ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-86 processor. ; ; Authors: Mike Lehman ; Herbert Yuen ; Bill Haygood ; Craig Franklin ; ; Date: 83-Apr-25 Monday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ ; 83-Jul-20 Haygood Small model conditional assembly code. ; 83-Oct-09 Craig Franklin Fix bug in medium model. ; 83-Oct-11 Haygood Use stack. sseg for new LINK86 V1.2. ; 83-Oct-15 Craig Franklin Use CLI/STI instead of slower PUSHF/POPF. ; 83-Oct-25 Craig Franklin Initialize zero divide handler. eject ; Notes to the user. ; ; Only the most sophisticated user, with a thorough knowledge of the 8086, ; CP/M, RASM86, LINK86, the .CMD file format, and the C calling conventions, ; should attempt to write a startup routine. These notes will explain how ; this one was written, and why certain things are done in certain ways. ; ; First of all, DRI has a new policy for assembly language routines: public ; names in them should not conflict with user public names, whether from a ; high level language or assembly language. This is accomplished by having ; a special in-house version of RASM86 which permits '.' (period) in an ; identifier as any but the first character. This startup routine uses that ; convention. When CLEAR, the Common Language Environment And Runtime is ; extended to all DRI languages, all internal (compiler referenced) runtime ; routines will contain a period, to avoid any conflict with a user name. ; ; This being the case, if you try to assemble this startup routine, you will ; get assembly errors. So you must alter your RASM86 by patching it. This ; is our way to insure that you really are a sophisticated user who knows what ; you are doing, otherwise you would not go to all this trouble. Using SID86, ; read in RASM86.CMD. The, using the SR (search) command, search for "$_?@". ; The byte before these four characters should be a hex 04, and the byte after ; should be a hex 00. Change the hex 04 to a hex 05. Change the hex 00 to a ; hex 2E (ASCII period). Now write RASM86.CMD back out to the disk. Period is ; now valid for the second and subsequent characters of an identifier. ; ; Now you can assemble this routine, or modify it. ; ; Note that the cseg is named 'cinit.' in lower case with a period in it. ; LINK86 puts this particular cseg FIRST in the .CMD file. This means that ; if the compiler does not emit a MOD END (module end) record with a starting ; address, and if no assembly routine contains END START, where START is a ; label, then LINK86 will NOT put five bytes of JMPF (or JMP/NOP/NOP) in the ; file to jump to the START address, and control will come to the initializer. ; LINK86 also puts the dseg 'dinit.' first in the data area of the .CMD file. ; You must use the RASM86 $nc option to assemble; otherwise the names will be ; CINIT. and DINIT., which LINK86 does not treat as special. ; ; This startup routine has been made modular for easy modification. ; There are basically six calls: initialize the stack, initialize the ; .CMD drive, perform the segment relocation (dummy routine in small model), ; initialize the heap, initialize the zerodivide handler, and call _main which ; parses the command line passed to it, opens the standard files (performing ; I/O redirection), and calls main. ; ; This one startup routine is the common source for all memory models. For ; example, 'retc' assembles to 'ret' in small model and to 'retf' in large model. eject ; include CLEAR ; Include CLEAR definitions. ; if C32 eq 0;-------------------------------------------------------------- CGROUP GROUP cinit. ; endif ;-------------------------------------------------------------- ; cinit. cseg ; ; extrn m.init.stack:near ; extrn m.init.cmd:near ; extrn m.init.reloc:near ; extrn m.init.heap:near ; extrn m.init.hardware.error:near extrn _main:far extrn main:far ; public m.init public _exit public m.init.error public m.error public m.init.run ; Dummy entry point public _v_reloc_8087 ; Dummy entry point ; m.init: call m.init.stack ; Initialize the stack. call m.init.cmd ; Find .CMD drive for overlay manager. call m.init.reloc ; Eliminate the R command call m.init.heap ; Initialize the heap. call m.init.hardware.error ; Initialize the zero divide handler. ; Note: must do them in the above order. ; heap must follow reloc, some versions of ; reloc must follow os, and stack must be first. ; Calls are short, because segment relocation ; may not be done until m.init.reloc finishes. ; Calls can be short because all four call ; targets use cinit. cseg in them. ; mov si,80h ; Offset of command line lodsb ; AL = length of command line. xor ah,ah push ax pushd ds ; Push DS if D32 (large data model) push si if D32 mov ss:.0,ds ; Needed for large model and overlay manager. endif callc _main jmps _exit ; Return to CP/M. ; jmpc main ; For debugging. ; m.init.error: ; Near call followed by fatal error message. pop dx push cs push dx ; m.error: ; Far call followed by fatal error message. pop dx ; DS:DX -> error message text. pop ds mov cl,9 ; BDOS function 9 will print a message. int 224 ; Call BDOS to print the error message. ; _exit: xor cx,cx int 224 ; Make sure to exit to O/S. ; m.init.run: ; Dummy entry point. Remove to use old LINK86. ret ; _v_reloc_8087: ; Dummy entry point until Fortran 77. retc ; ; end ; Name 'MINITSTACK' Title 'M.INIT.STACK' Pagesize 75 ; ; File name: MINITSTA.A86 ; ; Module name: M.INIT.STACK ; ; Entry parameters: None. ; ; Return value: None. ; ; Entry point Arguments Function ; ----------- --------- -------- ; ; m.init.stack None. Initialize the CLEAR stack. ; ; _salloc int n Allocate n bytes on the stack. ; ; Algorithm: With interrupts disabled (to allow for the ; defective versions of the 8088), set SS:SP, SL. ; ; Small model: Set SS = DS. Set SP from .6, ; the top of the DGROUP. ; SL. = HP. in minithea.a86. ; ; Large model: Set SS:SP from the base page. ; SL. is assembled in. ; ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-286 processor. ; ; Author: Bill Haygood ; ; Date: 83-Apr-25 Monday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ ; 83-May-05 Craig Franklin Allow RETF from .CMD to OS. ; 83-May-05 Craig Franklin Ignore stack size in BX. ; 83-Jun-14 Craig Franklin Delete reference to m.term. ; 83-Jul-20 Haygood Small model conditional assembly code. ; 83-Oct-09 Craig Franklin Fix bug in medium model. ; 83-Oct-11 Haygood Use stack. sseg for new LINK86 V1.2. ; 83-Oct-15 Craig Franklin Use CLI/STI instead of slower PUSHF/POPF. ; 83-Oct-22 Craig Franklin Add _salloc. eject ; include clear ; Get CLEAR definitions. ; if C32 eq 0;-------------------------------------------------------------- CGROUP GROUP cinit. ; endif ;-------------------------------------------------------------- ; cinit. cseg ; ; extrn m.init.error: near ; public m.init.stack, _salloc ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * M . I N I T . S T A C K * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; m.init.stack: pop ax ; Pop m.init return address. pop cx ; Pop system return address (this is a pop dx ; 32-bit address even in small model!). ; ; Disable interrupts to set SS:SP. (Early 8088 chips will fail if not.) ; sub bx,bx ; BX = 0 if D32 ;-------------------------------------------------------------- cli ; Disable interrupts. mov ss,15hÆbxÅ ; Setup stack segment register. mov sp,12hÆbxÅ ; Set stack offset. ; SL. is already set by assembly. sti ; Enable interrupts. else push ds ; SS = DS cli ; Disable interrupts. pop ss mov sp,6ÆbxÅ ; Initialize SP from base page. ; SL. is defined equ HP. in minithea.a86 sti ; Enable interrupts. endif ;-------------------------------------------------------------- inc sp ; Use all available allocated memory. and sp,0fffeh ; Align for iAPX-286 speed. eject ; ; Now construct the first stack frame. ; push dx ; Push system return address (this is a push cx ; 32-bit address even in small model!). push bx ; No previous stack frame. mov bp,sp ; Establish the first stack frame. lea dx,-8ÆbpÅ ; First stack frame is 8 words long. push dx ; Set SAVESP push bx ; Set ENLINK = 0 (no previous environment) push bx ; Set ONLINK = 0 (no previous on frame) push bx ; Set ONFRAME = 0 (no on units in frame) push ax ; Push m.init return address if D32 ;-------------------------------------------------------------- mov ss:.0,ds ; For large model to load for big model endif ;-------------------------------------------------------------- ret ; Return. ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * _ s a l l o c * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; _salloc: ; Allocate N bytes on the stack. pop bx ; Pop return address. popd cx pop dx ; Pop N. inc dx ; Round N to even. and dl,0feh if D32 ;-------------------------------------------------------------- mov ax,seg SL. mov es,ax mov ax,dx ; AX = N. add ax,es:SL. ; AX = SL. + N else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; mov ax,dx ; AX = N. add ax,SL. ; AX = SL. + N endif ;-------------------------------------------------------------- cmp ax,sp ; Would stack overflow? jbe stackok ; No. call m.init.error ; Yes, fatal error. db 'Stack overflow$' ; stackok: sub sp,dx ; Allocate N bytes. mov ax,sp ; SS:AX -> N bytes on stack. push dx ; Push N. pushd cx ; Push return address push bx if D32 ;-------------------------------------------------------------- mov bx,ss ; BX = SS for large model. endif ;-------------------------------------------------------------- retc ; Return BX:AX -> N bytes on stack. eject if D32 ;-------------------------------------------------------------- ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * D A T A * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; dseg ; public SL. ; SL. dw 14 ; Stack limit. Bias of 14 is for string routines. ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * S T A C K S T O R A G E A L L O C A T I O N * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; stack. sseg word ; stack. is special to LINK86 ; ; It causes .CMD MAX of 32K and ; ; .CMD MIN of 2K or total sseg size, ; ; whichever is greater. ; ; OSDS dw 0 ; DS from O/S ; public ONFRAME ; ; ; ONFRAME dw 0 ; dw seg ONFRAME ; else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; dseg extrn SL.:word endif ;-------------------------------------------------------------- ; ; end ; Name 'MINITCMD' Title 'M.INIT.CMD' Pagesize 75 ; ; File name: MINITCMD.A86 ; ; Module name: MINITCMD ; ; Arguments: None. ; ; Return value: _cmd_drive_bin .CMD drive in binary ; _cmd_drive_asc .CMD drive in ASCII ; ; Function: To determine the .CMD file drive. ; ; Algorithm: Look at location 50h in the base page. ; If it is non-zero, it is the binary .CMD drive. ; If it is zero, get the current drive from BDOS. ; In either case, add 'A' to get the ASCII drive. ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-286 processor. ; ; Author: Craig Franklin ; ; Date: 83-Oct-16 Sunday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ eject ; include clear ; Get CLEAR definitions. ; curdrive equ 25 ; BDOS call to return current drive. ; if C32 eq 0;-------------------------------------------------------------- CGROUP GROUP cinit. ; endif ;-------------------------------------------------------------- ; cinit. cseg ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m . i n i t . c m d * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; public m.init.cmd ; m.init.cmd: ; mov al,.50h ; AL = CMD drive number (1 to 20) dec al ; AL = 0 to 19. jns m.init.cmd.drive ; CMD drive was 0 (current drive) mov cl,curdrive int 224 ; m.init.cmd.drive: mov _cmd_drive_bin,al ; Store drive in binary. add al,'A' ; Convert it to ASCII. mov _cmd_drive_asc,al ; Store drive in ASCII. ret ; Return. ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * D A T A * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; The data items are declared in this peculiar way to be accessible from C. ; DGROUP GROUP _CMD_DRIVE_BIN,_CMD_DRIVE_ASC ; _CMD_DRIVE_BIN dseg common public _cmd_drive_bin _cmd_drive_bin db 0 ; _CMD_DRIVE_ASC dseg common public _cmd_drive_asc _cmd_drive_asc db 0 ; ; end ; Name 'MINITRELOC' Title 'M.INIT.RELOC' Pagesize 75 ; ; File name: MINITREL.A86 ; ; Module name: MINITRELOC ; ; Entry parameters: Stack exists. DS:0 -> base page. ; ; Return value: None. ; ; Errors: Must use R command or LINK86 V1.2 with this O/S ; ; Entry point Arguments ; ----------- --------- ; m.init.reloc None. ; ; m.init.reloc.buffer Pointer to null terminated relocation buffer. ; ; _v_reloc_segs Pointer to null terminated relocation buffer. ; Pointer to array of 8 overlay segment bases. ; Byte containing valid target relocation groups. ; ; Function: Relocate segment references in a program/overlay. ; WARNING: program must be linked by LINK86 V1.2. ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-286 processor. ; ; Author: Bill Haygood ; ; Date: 83-Apr-21 Thursday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ ; 83-Jul-19 Haygood Small model conditional assembly code. ; 83-Jul-30 Craig Franklin Emit warning if unable to relocate. ; 83-Aug-11 Craig Franklin Add C callable entry point for vcode. ; 83-Aug-30 Craig Franklin Correctly relocate within an overlay. ; 83-Sep-3 Craig Franklin Use new Link86 Aux Group 4 relocation. ; 83-Sep-13 Craig Franklin Repackage for C runtime. ; 83-Sep-23 Craig Franklin Optimize, compensate for LINK86 bug. ; 83-Sep-28 Craig Franklin Add medium model to small and large. ; 83-Sep-29 Craig Franklin Save SI and DI for caller REG variables. ; 83-Oct-15 Craig Franklin Relocate only when loading a segment. ; 83-Oct-18 Craig Franklin Add entry point for m.init.run to call. eject ; include clear ; Get CLEAR definitions. ; cinit. cseg ; public m.init.reloc ; ; extrn m.init.run: near ; extrn m.init.error: near ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * O F F S E T S F R O M B P * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; sidi equ -4 ; Space to save SI and DI. loadsegs equ -6 ; Mask of segments to relocate. overbases equ loadsegs -16 ; 8 group bases from overlay header. rootbases equ overbases-16 ; 8 group bases from program base page. ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m . i n i t . r e l o c * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; if (C32 eq 0) and (D32 eq 0) ; m.init.reloc: ret ; Small model -- no seg references. else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; public m.init.reloc.buffer ; Called only by m.init.run eject ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m . i n i t . r e l o c * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; m.init.reloc: mov cx,seg m.init.reloc ; Get a relocatable segment reference. jcxz need_relocation ; Relocation done already ? ret ; Yes, return to caller. ; need_relocation: mov cx,.45 ; CX = Aux Group 4 base address. jcxz old_LINK86 ; If 0, must be LINK86 before V1.2 ; ; Relocate the root using Aux Group 4 ; push ds ; Save caller DS. mov ds,.45 ; DS:SI-> AUX GROUP 4 sub si,si call m.init.reloc.buffer ; Relocate the root. pop ds ; Restore caller DS. ret ; Return to caller. ; old_LINK86: call m.init.run ; Last resort: try to open .CMD file ret ; ; Apply a relocation buffer to the root ; m.init.reloc.buffer: push bp ; Save caller BP. mov bp,sp ; Create new stack frame. mov ax,-1 ; AX = ffffh = relocate all segments. push ax ; Pretend to save SI and DI push ax ; to synchronize with _v_reloc_segs. push ax ; Push loadsegs. call pushbase ; Push the group start addresses. call reloc.buffer ; Do it all in only one call. mov sp,bp ; Reset SP. pop bp ; Restore caller BP. ret ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * _ v_ r e l o c * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; BUFFER equ ARG1 ; Offset from ÆBPÅ of buffer address. OVERBASE equ BUFFER +2+2*D32; Offset from ÆBPÅ of overlay bases. LOADSEGS equ OVERBASE+2+2*D32; Offset from ÆBPÅ of valid targets. ; public _v_reloc_segs ; _v_reloc_segs: pushd ds ; Save caller DS push bp ; Save caller BP mov bp,sp ; Address argument. push si ; Save caller SI. push di ; Save caller DI. push word ptr LOADSEGSÆbpÅ ; Push loadsegs for reloc.buffer. ; ; Push the overlay group start addresses ; ldx si,OVERBASEÆbpÅ ; DS:SI -> overlay bases from caller. ;if D32 ;-------------------------------------------------------------- push ss ; ES:DI -> stack frame overlay bases. pop es ; TEMPORARY UNTIL ES = SS always ;endif ;-------------------------------------------------------------- sub sp,16 ; Allocate space mov di,sp ; Allocate space mov cx,8 ; 8 groups rep movsw ; ; Relocate the buffer ; ldx si,BUFFERÆbpÅ ; DS:SI -> relocation buffer call reloc.buffer ; Process the relocation buffer lea sp,0-4ÆbpÅ ; Reset SP. pop di ; Restore caller DI. pop si ; Restore caller SI. pop bp ; Restore caller BP. popd ds ; Restore caller DS. retc eject ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * Subroutine to push the base page group start addresses * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; pushbase: pop ax ; AX = return address. mov bx,si ; BX = caller SI. mov dx,ds ; DX = caller DS. if D32 mov ds,ss:.0 ; DS = original DS from O/S else push ss ; DS = SS pop ds endif mov si,45 ; .45, .39, .33, .27, .21, .15, .9, .3 mov cx,8 ; Push 8 base addresses. ; pushloop: push word ptr ÆsiÅ ; Push the base. sub si,6 ; Locate next base. loop pushloop ; Loop. ; mov si,bx ; SI = caller SI. mov ds,dx ; DS = caller DS. push ax ; Push caller return address ret eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * P R O C E S S O N E R E L O C A T I O N B U F F E R * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; Register usage: ; ; (AX) Temporary. ; (BX) Byte offset in paragraph. ; (CX) Shift count. ; (DX) Segment base to add to memory. ; (DI) Tempor▶e1◀ry. ; (BP) Frame pointer to address loadsegs byte and two base tables ; (DS:SI) Relocation buffer entry. ; (ES:BX) Memory word to relocate. ; reloc.buffer: pop di ; DI = caller return address. call pushbase ; Push the root base addresses. push di ; Push caller return address. push si ; Save caller SI. sub ax,ax ; AX = 0 (for first LODSB). sub cx,cx ; CX = 0. jmps reloc.element.into ; Jump into loop. ; reloc.element.loop: ; ; Set DX = source group base ; sub al,11h ; Convert 1-8/1-8 to 0-7/0-7. mov di,ax ; DI = AX. and di,0007h ; DI = source group number (0-7). add di,di ; DI = source group number * 2. mov dx,rootbasesÆdi+bpÅ ; DX = source group base. ; ; Set DI = target group base ; and al,70h ; AX = target group number * 16. shr al,1 ; AX = target group number * 8. shr al,1 ; AX = target group number * 4. shr al,1 ; AX = target group number * 2. mov di,ax ; DI = target group number * 2. mov di,overbasesÆdi+bpÅ ; DI = target group base. ; ; Set BL = byte with a 1 bit in it for the target group ; shr al,1 ; AX = target group number * 1. mov cl,al ; CX = target group number. mov bl,1 ; BL = 1 for shift shl bl,cl ; BL = mask with 1 for target segment ; ; Compute address of memory word to add DX to ; lodsw ; AX = paragraph offset of memory word add di,ax ; DI = segment base of memory word mov es,di ; ES = DI sub ax,ax ; Clear AX for LODSB. lodsb ; AL = byte offset of memory word test bl,loadsegsÆbpÅ ; OK to relocate target segment? jz reloc.element.into ; No. mov bx,ax ; BX = byte offset add es:ÆbxÅ,dx ; Relocate memory word. ; reloc.element.into: lodsb ; AL = group number test al,0f0h ; End of buffer or fixup list ? jnz reloc.element.loop ; No. ; sub ax,ax ; Assume return false (done). pop bx ; BX = input SI sub si,bx ; SI = number of bytes processed. sub si,129 ; Full buffer processed? jnz reloc.element.return ; No, return 0 (last buffer). inc ax ; Yes, return 1 (more to come). ; reloc.element.return: if D32 eq 0;-------------------------------------------------------------- push ss ; Reset ES = SS for small model. pop es endif ;-------------------------------------------------------------- ret ; Return. ; endif ;---------------------------------------------------------------------- ; ; end ; Name 'MINITHEAP' Title 'M.INIT.HEAP' Pagesize 75 ; ; File name: MINITHEA.A86 ; ; Module name: MINITHEAP ; ; Entry point Arguments Function ; ----------- --------- -------- ; ; m.init.heap None. Initialize the heap. ; ; nbrk None Return the remaining ; heap size in bytes. ; Return (long)(HL.-HP.) ; ; sbrk int n Extend the heap n bytes. ; If HP. + n <= HL., ; set HP. = HP. + n ; ; brk char *p If HP. <= p <= HL., ; set HP. = p ; ; Algorithm: ; ; m.init.heap: ; ; Large: Set HP. to point to ESEG. ; Set HL. to point to HP. + size of ESEG. ; ; Small: Set HP. to point to the heap at the bottom of ; the free area. The stack is located at the top of the ; free area. Equivalence HL. and SL., the stack limit. ; ; nbrk: Set R = HP. - HL., if D32 set R *= 16, return R. ; ; sbrk: Round request r to bytes or paragraphs, set R = P = HP., ; set P = P+r, if P <= HL., set HP. = R and return R. ; ; brk: Compare pointer argument P to HP. and HL. ; If P >= HP. and P <= HL., set HP. = P, and ; return 0 (success), else return -1 (failure). ; ; In all of the above routines, HP. and HL. are one word ; pointers into the heap whose units are paragraphs. ; When sbrk returns the old HP., it is converted to a ; pointer with offset 0 in the large model. ; This is so the caller can use a full 64K byte offset with it. ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-286 processor. ; ; Author: Herbert Yuen and Bill Haygood ; ; Date: 83-Apr-11 Monday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ ; 06-Jul-83 Craig Franklin Add sbrk, brk entry points ; to correct 3 bugs in C versions. ; 83-Jul-19 Haygood Small model conditional assembly code. ; 83-Oct-11 Haygood Use heap. eseg for new LINK86 V1.2. ; 83-Oct-11 Craig Franklin Change retc to ret for C. Add nbrk. eject ; include clear ; Get CLEAR definitions. ; if D32 eq 0;-------------------------------------------------------------- slack equ 256 ; Allow for additional stack. endif ;-------------------------------------------------------------- ; cinit. cseg ; public m.init.heap, nbrk, sbrk, brk ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m . i n i t . h e a p * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; m.init.heap: if D32 ;-------------------------------------------------------------- mov ax,.0ch ; AX = low word of Extra Segment offset mov dh,.0eh ; DH = high byte of Extra Segment offset. add ax,15 ; Convert offset to paragraphs. jnc m.init.heap.nc ; Jump if not 64K boundary. inc dh ; 64K boundary. Increment high order. ; m.init.heap.nc: and al,0f0h ; Round bytes to paragraphs. mov cl,4 ; CL = 4 shr ax,cl ; Convert to paragraph number. shl dh,cl ; Convert to paragraph number. add ah,dh ; AX = paragraph number of heap size add ax,HP. ; AX = paragraph number of heap limit mov HL.,ax ; Set heap limit else push ds ; ES = DS pop es mov ax,?MEMRY ; Set up heap for brk(). mov HP.,ax endif ;-------------------------------------------------------------- ret eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * n b r k * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; nbrk: if D32 ;-------------------------------------------------------------- mov ax,seg HP. ; AX = seg HP. mov es,ax ; Set ES = seg HP. mov ax,es:HL. ; AX = heap limit. sub ax,es:HP. ; AX = heap size = heap limit - heap base. mov bx,16 mul bx ; Convert paragraphs to long int bytes. mov bx,dx ; In AX/BX. retc ; Return. else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; mov ax,sp ; AX = heap limit. sub ax,slack ; Allow for additional stack. sub ax,HP. sub bx,bx ; Return long int bytes. retc ; Return. endif ;-------------------------------------------------------------- ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * s b r k * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; sbrk: if D32 ;-------------------------------------------------------------- mov bx,sp ; Address argument mov dx,ss:2+2*C32ÆbxÅ ; Get allocation size in bytes. add dx,15 ; Round up to next paragraph. and dl,0f0h mov cl,4 ; CL = 4 shr dx,cl ; Convert bytes to paragraphs push ds ; Save caller DS (large model) mov bx,seg HP. ; BX = DS of HP. mov ds,bx ; Set DS mov bx,HP. ; BX = old heap pointer (in paragraphs) sub ax,ax ; BX:AX = old HP.:0 = pointer to area add dx,bx ; DX = new heap pointer (in paragraphs) cmp dx,HL. ; Will it fit ? ja xbrk.fail ; No. Fail. mov HP.,dx ; Update HP. pop ds ; Restore original DS. retc ; Return BX:AX = old HP.:0. ; xbrk.fail: ; Set AX = -1 (failure) and return. mov ax,-1 ; AX = -1 mov bx,ax pop ds ; Restore original DS. retc ; Return. ; else mov bx,sp ; BX = SP mov bx,ss:2+2*C32ÆbxÅ ; Get argument. inc bx ; Round up to even byte boundary. and bl,0feh mov ax,HP. ; Get current heap pointer. add bx,ax ; Did wrap around occur ? jc xbrk.fail ; Yes. jmps xbrk ; xbrk.fail: ; Set AX = -1 (failure) and return. mov ax,-1 ; AX = -1 ret ; Return. endif ;-------------------------------------------------------------- eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * b r k * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; brk: if D32 ;-------------------------------------------------------------- mov bx,sp ; BX = SP push ds ; Save caller DS (large model) mov ax,ss:2+2*C32ÆbxÅ ; AX = pointer offset mov bx,ss:4+2*C32ÆbxÅ ; BX = pointer segment add ax,15 ; Round AX from bytes to paragraphs jnc brk.ok ; Carry ? add bx,1000h ; Yes, add 64K bytes to segment. ; brk.ok: mov cl,4 ; CL = 4 shr ax,cl add ax,bx ; And add in segment cmp ax,HP. ; Below current heap pointer? jb xbrk.fail ; Yes. Fail. cmp ax,HL. ; Above heap limit? ja xbrk.fail ; Yes. Fail. mov HP.,ax ; Reset heap pointer sub ax,ax ; Succeed. pop ds ; Restore caller DS else mov bx,sp mov bx,ss:2+2*C32ÆbxÅ ; Get parameter - brk address. sub ax,ax ; AX = 0 for success ; xbrk: mov cx,sp ; CX = SP sub cx,slack ; Allow for additional stack. cmp bx,cx ; Below stack pointer ? jae xbrk.fail ; No. cmp bx,HP. ; Above heap pointer ? jb xbrk.fail ; No. mov HP.,bx ; Set new heap pointer. endif ;-------------------------------------------------------------- retc ; Return. eject ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * D A T A * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; dseg ; if D32 ;-------------------------------------------------------------- HP. dw seg ES. ; Heap pointer in paragraphs. ; HL. dw 0 ; Heap limit in paragraphs. ; ; ; (Set by m.init.heap.) ; ; ; heap. is special to LINK86: it sets .CMD MAX to 32K and .CMD MIN to 2k or ; eseg total, whichever is larger. ; heap. eseg ; ; ; ES. rw 0 ; else ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; public ?MEMRY, HP., SL. ; ?MEMRY rw 1 ; Initialized by LINK86. ; HP. rw 1 ; Heap pointer in bytes. ; SL. equ HP. ; Is also stack limit in bytes. ; endif ;-------------------------------------------------------------- ; ; end ; Name 'MINITERROR' Title 'M.INIT.ERROR' Pagesize 75 ; ; File name: MINITER.A86 ; ; Module name: MINITERROR ; ; Entry parameters: None. ; ; Return value: None. ; ; Entry point Arguments ; ----------- --------- ; ; m.init.hardware.error None. ; ; Function: To initialize the runtime system integer zero ; divide error handler. ; ; Algorithm: Place the vector to the integer zero divide ; handler in absolute location 0:0. ; ; Source language: DRI RASM-86 ; ; Target environment: Intel iAPX-286 processor. ; ; Author: Bill Haygood ; ; Date: 83-Apr-07 Thursday ; ; Revision history: ; ; When Who Why and what ; ---- --- ------------ ; 83-Jul-20 Haygood Small model conditional assembly code. ; 83-Oct-25 Craig Franklin Abort with error message. eject ; include clear ; Get CLEAR definitions. ; if C32 eq 0;-------------------------------------------------------------- CGROUP GROUP cinit. ; endif ;-------------------------------------------------------------- ; cinit. cseg ; ; extrn m.init.error: near ; public m.init.hardware.error ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * m . i n i t . h a r d w a r e . e r r o r * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; Initialize the zero divide vector. ; m.init.hardware.error: push ds ; Save original DS. sub bx,bx ; BX -> offset 0 mov ds,bx ; DS = 0 mov ÆbxÅ,offset zerodiv ; Store the zero divide handler pointer mov 2ÆbxÅ,cs ; at hardware locations 0 and 2. pop ds ; Restore original DS. ret ; Return. ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; * * ; * z e r o d i v * ; * * ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; Integer zero divide handler. ; zerodiv: call m.init.error ; Fatal error db 'Zero divide error$' ; end «eof»