; $Header: D:/logfiles/masters/lowlvasm.jpv 1.1 17 Mar 1991 18:18:08 coleb $ ; ; LOWLEVEL.ASM ; ; Assembly routines for LowLevel module from PMI. ; JPI version ; ; For Repertoire Version 1.6 ; LowLevel_TEXT SEGMENT BYTE 'CODE' PUBLIC LowLevel_TEXT ENDS LowLevel_BSS SEGMENT BYTE 'FAR_DATA' PUBLIC LowLevel@Initialized DW ? LowLevel_BSS ENDS LowLevel_CONST SEGMENT BYTE 'FAR_DATA' PUBLIC LowLevel_CONST ENDS LowLevelDGROUP GROUP LowLevel_CONST, LowLevel_BSS ;============================================================================ LowLevel_CONST SEGMENT ;---------------------------------------------------------------------------- PUBLIC LowLevel$ LowLevel$ DD LowLevel$Init DB 255 DB 255 LowLevel_CONST ENDS ;============================================================================ ASSUME CS:LowLevel_TEXT ASSUME DS:LowLevel_BSS LowLevel_TEXT SEGMENT ;---------------------------------------------------------------------------- PUBLIC LowLevel$Init EXTRN _api_init:FAR LowLevel$Init PROC FAR PUSH DS MOV AX, LowLevel_BSS MOV DS, AX MOV AX, LowLevel@Initialized CMP AX, 1 JE InitEnd call _api_init MOV AX, 1 MOV LowLevel@Initialized, AX InitEnd: POP DS RET 0 LowLevel$Init ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$AddAddr LowLevel$AddAddr PROC FAR PUSH BP ;Set up stack frame MOV BP, SP MOV AX, 6[BP] ;bytes to add to address ADD AX, 8[BP] ;offset of address MOV DX, 10[BP] ;segment of address POP BP ;restore frame pointer RET 6 LowLevel$AddAddr ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$BitwiseAnd LowLevel$BitwiseAnd PROC FAR PUSH BP ;Set up stack frame MOV BP, SP MOV AX, 8[BP] ;val1 goes into AX AND AX, 6[BP] ;AND it with val2; result stays in AX POP BP ;restore frame pointer RET 4 LowLevel$BitwiseAnd ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$SubAddr LowLevel$SubAddr PROC FAR PUSH BP ;Set up stack frame MOV BP, SP MOV AX, 8[BP] ;offset of old address SUB AX, 6[BP] ;subtract bytes MOV DX, 10[BP] ;segment of address POP BP ;restore frame pointer RET 6 LowLevel$SubAddr ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$DecAddr LowLevel$DecAddr PROC FAR PUSH BP ;Set up stack frame MOV BP, SP PUSH BX MOV AX, 6[BP] ;bytes to subtract from address LES BX, 8[BP] ;address of TheAdr SUB ES:[BX], AX ;subtract from address POP BX POP BP ;restore frame pointer RET 6 LowLevel$DecAddr ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$IncAddr LowLevel$IncAddr PROC FAR PUSH BP ;Set up stack frame MOV BP, SP PUSH BX MOV AX, 6[BP] ;bytes to add address LES BX, 8[BP] ADD ES:[BX], AX ;add to address POP BX POP BP ;restore frame pointer RET 6 LowLevel$IncAddr ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$InByte LowLevel$InByte PROC FAR PUSH BP ;set up frame pointer MOV BP, SP PUSH BX MOV DX, 10[BP] ;Port IN AL, DX ;Get the byte LES BX, 6[BP] ;Address of value MOV ES:[BX], AL ;Store it POP BX POP BP ;restore frame pointer RET 6 LowLevel$InByte ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$OutByte LowLevel$OutByte PROC FAR PUSH BP ;set up frame pointer MOV BP, SP MOV DX, 8[BP] ;Port MOV AL, 6[BP] ;value OUT DX, AL ;Put the byte POP BP ;restore frame pointer RET 4 LowLevel$OutByte ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$OutWord LowLevel$OutWord PROC FAR PUSH BP ;set up frame pointer MOV BP, SP MOV DX, 8[BP] ;Port MOV AX, 6[BP] ;value OUT DX, AX ;Put the word POP BP ;restore frame pointer RET 4 LowLevel$OutWord ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$InWord LowLevel$InWord PROC FAR PUSH BP ;set up frame pointer MOV BP, SP PUSH BX MOV DX, 10[BP] ;Port IN AX, DX ;Get the byte LES BX, 6[BP] ;Address of value MOV ES:[BX], AX ;Store it POP BX POP BP ;restore frame pointer RET 6 LowLevel$InWord ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$Interrupt IntParams STRUC DW ?, ?, ? TheRegs DD ? InterruptNumber DW ? IntParams ENDS LowLevel$Interrupt PROC FAR PUSH BP ;Set up stack frame MOV BP, SP PUSH BX ;Save needed registers PUSH CX PUSH SI PUSH DI PUSH DS MOV AX, SS ;Save stack seg and pointer MOV CS:StackSeg, AX ;since some interrupts may clobber them MOV CS:StackPtr, SP ; ; Set up the stack to fake an interrupt by doing a jump ; PUSHF ;Flags PUSH CS LEA AX, IntRet ;Interrupt return point PUSH AX MOV BX, InterruptNumber[BP] ;Interrupt number SHL BX, 1 ;Convert to long address SHL BX, 1 XOR AX, AX ;Segment 0 MOV DS, AX PUSH 2[BX] ;Interrupt handler segment PUSH [BX] ;Interrupt handler offset ; ; Set up the registers as requested in TheRegs from the calling ; parameters ; LDS SI, TheRegs[BP] ;Pointer to record MOV AX, [SI] MOV BX, 2[SI] MOV CX, 4[SI] MOV DX, 6[SI] MOV BP, 8[SI] PUSH 10[SI] ;Not ready for this yet MOV DI, 12[SI] MOV ES, 16[SI] MOV DS, 14[SI] POP SI ;Now I'm ready for it RET ;do the interrupt IntRet: PUSH CS:StackSeg ;old stack segment POP SS MOV SP, CS:StackPtr ;old stack pointer PUSHF ;returned flags PUSH BP ;save this too MOV BP, SP ;old frame pointer ADD BP, 14 ;allow for stuff on stack PUSH DS ;Need these for output PUSH DI LDS DI, TheRegs[BP] ;Address of register structure POP 12[DI] ;Returned DI POP 14[DI] ;Returned DS POP 8[DI] ;Returned BP MOV [DI], AX MOV 2[DI], BX MOV 4[DI], CX MOV 6[DI], DX MOV 10[DI], SI MOV 16[DI], ES POP 18[DI] ;flags ; ; Restore registers and return ; POP DS POP DI POP SI POP CX POP BX POP BP ; and frame pointers RET 6 LowLevel$Interrupt ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$EMInterrupt LowLevel$EMInterrupt PROC FAR PUSH BP ;save frame pointer MOV BP, SP PUSH BX MOV AL, 6[BP] ;function LES BX, 8[BP] ;address of TheRegs structure MOV ES:[BX+1], AL ;set function in AX MOV AX, 67H ;EM interrupt number PUSH AX PUSH ES ;Segment of regs structure PUSH BX ;Offset of regs structure CALL LowLevel$Interrupt ;Call general interrupt routine POP BX POP BP RET 6 LowLevel$EMInterrupt ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$VideoInterrupt LowLevel$VideoInterrupt PROC FAR PUSH BP ;save frame pointer MOV BP, SP LES DX, 6[BP] ;address of TheRegs structure MOV AX, 10H ;EM interrupt number PUSH AX PUSH ES ;Segment of regs structure PUSH DX ;Offset of regs structure CALL LowLevel$Interrupt ;Call general interrupt routine POP BP RET 4 LowLevel$VideoInterrupt ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$msdos LowLevel$msdos PROC FAR PUSH BP ;save frame pointer MOV BP, SP LES DX, 6[BP] ;address of TheRegs structure MOV AX, 21H ;EM interrupt number PUSH AX PUSH ES ;Segment of regs structure PUSH DX ;Offset of regs structure CALL LowLevel$Interrupt ;Call general interrupt routine POP BP RET 4 LowLevel$msdos ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$FlaggedError LowLevel$FlaggedError PROC FAR PUSH BP ;Set up Frame Pointer MOV BP, SP MOV AX, 6[BP] ;Flags register to test AND AX, 1 ;Carry Flag POP BP ;Restore Previous Frame Pointer RET 2 LowLevel$FlaggedError ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$seg LowLevel$seg PROC FAR PUSH BP ;Set up Frame Pointer MOV BP,SP MOV AX, 8[BP] ;Segment of argument POP BP ;Restore Frame pointer RET 4 LowLevel$seg ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ofs LowLevel$ofs PROC FAR PUSH BP ;Set up Frame Pointer MOV BP,SP MOV AX, 6[BP] ;Offset of argument POP BP ;Restore Frame Pointer RET 4 LowLevel$ofs ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$Ptr LowLevel$Ptr PROC FAR PUSH BP ;Set up Frame Pointer MOV BP, SP MOV AX, 6[BP] ;Offset MOV DX, 8[BP] ;Segment POP BP ;Restore Frame Pointer RET 4 LowLevel$Ptr ENDP ;-------------------------------------------------------------------- PUBLIC LowLevel$PeekByte LowLevel$PeekByte PROC FAR PUSH BP ;Set up Frame Pointer MOV BP,SP PUSH BX ;BX must be preserved during call LES BX, 6[BP] ;Address of value to return MOV AX, ES:[BX] ;Return value MOV AH, 0 ;Make sure caller ignores high byte POP BX ;Restore for caller POP BP ;Restore frame pointer RET 4 LowLevel$PeekByte ENDP ;-------------------------------------------------------------------- PUBLIC LowLevel$PeekWord LowLevel$PeekWord PROC FAR PUSH BP ;Set up Frame Pointer MOV BP,SP PUSH BX ;BX must be preserved during call LES BX, 6[BP] ;Address of value to return MOV AX, ES:[BX] ;Return value POP BX ;Restore for caller POP BP ;Restore frame pointer RET 4 LowLevel$PeekWord ENDP ;-------------------------------------------------------------------- PokeParams STRUC DW 3 DUP (?) PokeLoc DD ? PokeData DW ? PokeParams ENDS PUBLIC LowLevel$PokeWord LowLevel$PokeWord PROC FAR PUSH BP ;Set up Frame Pointer MOV BP, SP PUSH BX ;Save for caller LES BX, PokeLoc[BP] ;Address to put word at MOV AX, PokeData[BP];Value to poke MOV ES:[BX], AX ;Stuff it there POP BX ;Restore for caller POP BP ;Restore Frame Pointer RET 6 LowLevel$PokeWord ENDP PUBLIC LowLevel$PokeByte LowLevel$PokeByte PROC FAR PUSH BP ;Set up Frame Pointer MOV BP, SP PUSH BX ;Save for caller LES BX, PokeLoc[BP] ;Address to put word at MOV AX, PokeData[BP];Value to poke MOV ES:[BX], AL ;Stuff it there POP BX ;Restore for caller POP BP ;Restore Frame Pointer RET 6 LowLevel$PokeByte ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ShiftArrayLeft ArrayParams STRUC DW 3 DUP(?) distance DW ? TheSize DW ? ArrayAdr DD ? ArrayParams ENDS LowLevel$ShiftArrayLeft PROC FAR ; ; Moving bytes to lower memory ; PUSH BP ;Set up Frame Pointer MOV BP, SP PUSH CX ;Save for caller MOV CX, TheSize[BP] SUB CX, distance[BP];Number of bytes to move JLE ArrayLeftExit ;Moving zero or fewer bytes PUSH DI ;Save altered registers PUSH SI PUSH DS LDS SI, ArrayAdr[BP] ;Source ADD SI, distance[BP] ;Moving bytes to lower memory LES DI, ArrayAdr[BP] ;Destination CLD REP MOVSB POP DS ;Restore altered registers POP SI POP DI ArrayLeftExit: POP CX POP BP RET 8 LowLevel$ShiftArrayLeft ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ShiftArrayRight LowLevel$ShiftArrayRight PROC FAR ; ; Moving bytes to higher memory ; PUSH BP ;Set up Frame Pointer MOV BP, SP PUSH CX ;Save for caller MOV CX, TheSize[BP] SUB CX, distance[BP];Number of bytes to move JLE ArrayLeftExit ;Moving zero or fewer bytes PUSH DI ;Save altered registers PUSH SI PUSH DS LDS SI, ArrayAdr[BP] ;Source ADD SI, CX ;CX is number of bytes to move DEC SI ;Last byte to move LES DI, ArrayAdr[BP] ;Destination ADD DI, TheSize[BP] DEC DI ;Last byte to move STD REP MOVSB CLD POP DS ;Restore altered registers POP SI POP DI ArrayRightExit: POP CX POP BP RET 8 LowLevel$ShiftArrayRight ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ShiftLeft ShftParams STRUC DW 0,0,0 HowMany DW ? TheWord DD ? ShftParams ENDS LowLevel$ShiftLeft PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX PUSH SI LES SI,TheWord[BP] MOV AX,ES:[SI] MOV CX,HowMany[BP] SHL AX,CL MOV ES:[SI],AX POP SI POP CX POP BP RET 6 LowLevel$ShiftLeft ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ShiftRight LowLevel$ShiftRight PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX PUSH SI LES SI,TheWord[BP] MOV AX,ES:[SI] MOV CX,HowMany[BP] SHR AX,CL MOV ES:[SI],AX POP SI POP CX POP BP RET 6 LowLevel$ShiftRight ENDP MoveParams STRUC DW 0,0,0 Move_dsize DW ? dest DD ? source DD ? MoveParams ENDS ;---------------------------------------------------------------------------- PUBLIC LowLevel$Move LowLevel$Move PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX MOV CX, Move_dsize[BP] OR CX,CX JZ Move_Exit PUSH DI PUSH SI PUSH DS PUSH ES LDS SI,source[BP] LES DI,dest[BP] CLD REP MOVSB POP ES POP DS POP SI POP DI Move_Exit: POP CX POP BP RET 10 LowLevel$Move ENDP FillParams STRUC DW 0,0,0 thefill DW ? fsize DW ? fdest DD ? FillParams ENDS ;---------------------------------------------------------------------------- PUBLIC LowLevel$Fill LowLevel$Fill PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX MOV CX, fsize[BP] OR CX,CX JZ Fill_Exit PUSH AX PUSH DI PUSH ES MOV AX, thefill[BP] LES DI, fdest[BP] CLD REPNZ STOSB POP ES POP DI POP AX Fill_Exit: POP CX POP BP RET 8 LowLevel$Fill ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$FillWord LowLevel$FillWord PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX MOV CX, fsize[BP] OR CX,CX JZ FillWord_Exit PUSH AX PUSH DI PUSH ES MOV AX, thefill[BP] LES DI, fdest[BP] CLD REPNZ STOSW POP ES POP DI POP AX FillWord_Exit: POP CX POP BP RET 8 LowLevel$FillWord ENDP EQParams STRUC DW 0,0,0 start DD ? lookfor DB ?,0 EQsize DW ? EQParams ENDS ;---------------------------------------------------------------------------- PUBLIC LowLevel$ScanEQ LowLevel$ScanEQ PROC FAR ; Starting at the address start, scan size bytes at most, ; looking for lookfor. If size is negative, look backwards ; from start. Result is number of bytes skipped to get to ; lookfor, or size if not found PUSH BP ;set up stack frame MOV BP,SP PUSH DI PUSH CX PUSH BX LES DI,start[BP] MOV AL,lookfor[BP] MOV CX,EQsize[BP] MOV BX,CX ;size OR CX,CX JLE EQBack ; ; size is > 0 ; INC CX ;i CLD REPNZ SCASB SUB BX,CX ;size - i JMP EQExit EQBack: JZ EQZero ; ; size is < 0 NEG CX INC CX ;i STD REPNZ SCASB CLD ADD BX,CX ;size+i JMP EQExit EQZero: MOV BX,0 ;return 0 ; ;size was 0 ; EQExit: MOV AX,BX ;return value POP BX POP CX POP DI POP BP RET 8 LowLevel$ScanEQ ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$ScanNE LowLevel$ScanNE PROC FAR ; Starting at the address start, scan size bytes at most, ; looking for not lookfor. If size is negative, look backwards ; from start. Result is number of bytes skipped to get to something that ; is not lookfor, or size if not found PUSH BP ;set up stack frame MOV BP,SP PUSH DI PUSH CX PUSH BX LES DI,start[BP] MOV AL,lookfor[BP] MOV CX,EQsize[BP] MOV BX,CX ;size OR CX,CX JLE NEBack ; ; size is > 0 ; INC CX ;i CLD REPZ SCASB SUB BX,CX ;size - i JMP NEExit NEBack: JZ NEZero ; ; size is < 0 NEG CX INC CX ;i STD REPZ SCASB CLD ADD BX,CX ;size+i JMP NEExit NEZero: MOV BX,0 ;return 0 ; ;size was 0 ; NEExit: MOV AX,BX ;return value POP BX POP CX POP DI POP BP RET 8 LowLevel$ScanNE ENDP ;---------------------------------------------------------------------------- PUBLIC LowLevel$WriteDMANoSnow DMAParams STRUC DW 0,0,0 dsize DW ? ToAddr DD ? FromAddr DD ? DMAParams ENDS LowLevel$WriteDMANoSnow PROC FAR PUSH BP ;set up stack frame MOV BP,SP PUSH CX PUSH DI PUSH SI PUSH DS LES DI,ToAddr[BP] LDS SI,FromAddr[BP] MOV CX,dsize[BP] MOV DX,3DAH; TOP1: IN AL, DX ; wait until Vertical retrace TEST AL, 08H ; not in progress JNZ TOP1 CLD TEST CX, 0FFFFH CHKH: JZ END1 ; exit if nothing left to write TOP2: IN AL, DX ; wait until Horiz. retrace TEST AL, 01H ; not in progress JNZ TOP2 IN AL, DX ; IF in Vertical retrace TEST AL, 08H ; goto block move JNZ TOPV CLI TOPH: IN AL, DX ; wait until Horiz. retrace TEST AL, 01H ; in progress JZ TOPH MOVSB ; write one byte STI DEC CX ; dec count and go to top JMP CHKH TOPV: REPNZ MOVSB ; then move line END1: NOP POP DS POP SI POP DI POP CX POP BP RET 0AH LowLevel$WriteDMANoSnow ENDP StackSeg DW ? StackPtr DW ? LowLevel_TEXT ENDS END