--- /dev/null
+; MMURTL Operating System Source Code\r
+; Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+; ALL RIGHTS RESERVED Version 1.0\r
+\r
+;===============================================\r
+.CODE\r
+\r
+;The following calls are miscellaneous support functions that\r
+;support I/O and high speed string functions on the 80386/486\r
+;processors. They are made accessible via call gates to all\r
+;users (except for the I/O ops which are limited to supervisor\r
+;level callers).\r
+\r
+; OutByte(Byte, dPort)\r
+; OutWord(Word,dPort)\r
+; OutWords(dPort,pDataOut,dBytes)\r
+; OutDWord(DWord, dPort)\r
+; InByte(dPort):Byte\r
+; InWord(dPort):Word\r
+; InWords(dPort, pDataIn,dBytes)\r
+; InDWord(dPort):DWord\r
+; ReadCMOS(bAddress):Byte\r
+; CopyData(pSource, pDestination, dBytes)\r
+; CopyDataR(pSource, pDestination, dBytes)\r
+; FillData(pDest, cBytes, bFill)\r
+; CompareNCS(pS1, pS2, dSize) : returned offset or -1\r
+; Compare(pS1, pS2, dSize) : returned offset or -1\r
+\r
+;===============================================\r
+; OutByte(Byte, wPort)\r
+; The Byte is sent out the I/O Port specified.\r
+; Byte = [EBP+16]\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __OutByte:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ MOV AL, BYTE PTR [EBP+16]\r
+ OUT DX, AL\r
+ POP EBP\r
+ RETF 8 ;\r
+;\r
+;===============================================\r
+; OutWord(Word, wPort)\r
+; The Word is sent out the I/O Port specified.\r
+; Word = [EBP+16]\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __OutWord:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ MOV AX, WORD PTR [EBP+16]\r
+ OUT DX, AX\r
+ POP EBP\r
+ RETF 8 ;\r
+\r
+;===============================================\r
+; OutWords(wPort, pDataOut, dBytes)\r
+; The dBytes/2 are sent out to wPort from the pDataOut address\r
+; wPort = [EBP+20]\r
+; pDataOut = [EBP+16]\r
+; dBytes = [EBP+12]\r
+;\r
+PUBLIC __OutWords:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+20]\r
+ MOV ESI, DWORD PTR [EBP+16]\r
+ MOV ECX, DWORD PTR [EBP+12]\r
+ SHR ECX, 1 ;Make WORDS vice bytes\r
+ CLD\r
+ REP OUTSW\r
+ POP EBP\r
+ RETF 12 ;\r
+;\r
+;===============================================\r
+; OutDWord(DWord, wPort)\r
+; The Word is sent out the I/O Port specified.\r
+; DWord = [EBP+16]\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __OutDWord:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ MOV EAX, DWORD PTR [EBP+16]\r
+ OUT DX, EAX\r
+ POP EBP\r
+ RETF 8 ;\r
+;\r
+;===============================================\r
+; InByte(wPort)\r
+; The Byte is read from the I/O Port specified and returned in AL\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __InByte:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ IN AL, DX\r
+ AND EAX, 0FFh ;Only get the byte\r
+ POP EBP\r
+ RETF 4 ;\r
+;\r
+;===============================================\r
+; InWord(wPort)\r
+; The Byte is read from the I/O Port specified and returned in AX\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __InWord:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ IN AX, DX\r
+ AND EAX, 0FFFFh ;Only get the Word\r
+ POP EBP\r
+ RETF 4 ;\r
+;\r
+;===============================================\r
+; InWords(wPort, pDataIn, dBytes)\r
+; The dBytes/2 are read in from wPort to pDataIn\r
+; wPort = [EBP+20]\r
+; pDataIn = [EBP+16]\r
+; dBytes = [EBP+12]\r
+;\r
+; ASSUMES ES == DS !!!! (In MMURTL it always does...)\r
+;\r
+PUBLIC __InWords:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+20]\r
+ MOV EDI, DWORD PTR [EBP+16]\r
+ MOV ECX, DWORD PTR [EBP+12]\r
+ SHR ECX, 1 ;Make WORDS vice bytes\r
+ CLD\r
+ REP INSW\r
+ POP EBP\r
+ RETF 12 ;\r
+;\r
+;===============================================\r
+; InDWord(wPort)\r
+; The Byte is read from the I/O Port specified and returned in EAX\r
+; wPort = [EBP+12]\r
+;\r
+PUBLIC __InDWord:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV DX, WORD PTR [EBP+12]\r
+ IN EAX, DX\r
+ POP EBP\r
+ RETF 4 ;\r
+\r
+;===============================================\r
+; ReadCMOS(wAddress)\r
+; The Byte is read from the CMOS address specified and returned in AL\r
+; wAddress = [EBP+12]\r
+;\r
+PUBLIC __ReadCMOS:\r
+ PUSH EBP\r
+ MOV EBP, ESP\r
+ MOV AL, BYTE PTR [EBP+12]\r
+ OR AL, 80h\r
+ CLI\r
+ OUT 70h,AL\r
+ NOP\r
+ NOP\r
+ NOP\r
+ NOP\r
+ IN AL, 71h\r
+ STI\r
+ AND EAX, 0FFh\r
+ POP EBP\r
+ RETF 4 ;\r
+\r
+;===============================================\r
+;\r
+; CopyData(pSource, pDestination, dBytes)\r
+;\r
+; pSource is address of place to copy from,\r
+; pDestination is address of place to copy to,\r
+; and cBytes is number of bytes to copy\r
+;\r
+; A usefull routine that ALWAYS moves DWORDS\r
+; when possible. We test to see if there is an\r
+; odd byte, if so we move it. Then check for an\r
+; odd word, if there, we move it. Then we move\r
+; the rest with MOVSD (whole DWORDS!).\r
+; WARNING: ASSUMES ES = DS !!!!\r
+; Do NOT use to shift data in an array to the right,\r
+; use CopyDataR instead. CopyData can be used\r
+; to shift data to the left in an array safely.\r
+;\r
+;pSource [EBP + 20]\r
+;pDest [EBP + 16]\r
+;cBytes [EBP + 12]\r
+;\r
+PUBLIC __CopyData PROC FAR\r
+ PUSH EBP\r
+ MOV EBP,ESP\r
+ MOV EDI,[EBP+16] ;Load destination address\r
+ MOV ESI,[EBP+20] ;Load source address\r
+ MOV ECX,[EBP+12] ;Load count of bytes to move\r
+ CLD ;Auto incrementing move\r
+ SHR ECX,1 ;Check odd byte\r
+ JNC NoByteC\r
+ MOVSB ;Handle the odd byte\r
+NoByteC:\r
+ SHR ECX,1 ;Check odd word\r
+ JNC NoWordC\r
+ MOVSW ;Handle the odd word\r
+NoWordC:\r
+ REP MOVSD ;Move all DWORDS that are left\r
+ POP EBP\r
+ RETF 12 ;Pop args off the stack\r
+\r
+;===============================================\r
+;\r
+; CopyDataR(pSource, pDestination, dBytes)\r
+;\r
+; pSource is begining address of place to copy from,\r
+; pDestination is begining address of place to copy to,\r
+; and cBytes is number of bytes to copy\r
+;\r
+; Same as CopyData except data is copied from\r
+; the higest addresses of pSource and pDest first.\r
+; (e,g, pSource+dBytes => pDest+dBytes)\r
+; WARNING: ASSUMES ES = DS !!!!\r
+; Do NOT use to shift data in an array to the left,\r
+; use CopyData instead. CopyDataR can be used\r
+; to shift data to the left in an array safely.\r
+;\r
+;pSource [EBP + 20]\r
+;pDest [EBP + 16]\r
+;cBytes [EBP + 12]\r
+;\r
+PUBLIC __CopyDataR:\r
+ PUSH EBP\r
+ MOV EBP,ESP\r
+ MOV EDI,[EBP+16] ;Load destination address\r
+ MOV ESI,[EBP+20] ;Load source address\r
+ MOV ECX,[EBP+12] ;Load count of bytes to move\r
+ STD ;Auto Decrement\r
+ ADD ESI, ECX ;Point to end of strings\r
+ ADD EDI, ECX\r
+ DEC ESI ;correct addresses after addition\r
+ DEC EDI\r
+ SHR ECX,1 ;Check odd byte\r
+ JNC NoByteR\r
+ MOVSB ;Handle the odd byte\r
+NoByteR:\r
+ SHR ECX,1 ;Check odd word\r
+ JNC NoWordC\r
+ MOVSW ;Handle the odd word\r
+NoWordR:\r
+ REP MOVSD ;Move all DWORDS that are left\r
+ POP EBP\r
+ RETF 12 ;Pop args off the stack\r
+\r
+;===============================================\r
+;\r
+; FillData(pDest, cBytes, bFill)\r
+;\r
+; pDestination is begining address to fill\r
+; cBytes is the size of the fill area\r
+; bFill is the byte value to fill with\r
+;\r
+; Trys to use DWORDS if it can.\r
+;\r
+;pDest [EBP + 20]\r
+;cBytes [EBP + 16]\r
+;bFill [EBP + 12]\r
+;\r
+PUBLIC __FillData:\r
+ PUSH EBP\r
+ MOV EBP,ESP\r
+ MOV AL, BYTE PTR [EBP+12] ;Byte to fill with\r
+ MOV AH,AL ;Set up to store DWords\r
+ SHL EAX,8\r
+ MOV AL,AH\r
+ SHL EAX,8\r
+ MOV AL,AH ;Byte is now in all four of EAX\r
+ MOV EDI, DWORD PTR [EBP+20] ;Load destination address\r
+ MOV ECX, DWORD PTR [EBP+16] ;Load count of bytes to fill\r
+ CLD ;Auto-increment\r
+ SHR ECX,1 ;Check even/odd\r
+ JNC NoByteF\r
+ STOSB ;Handle the odd byte\r
+NoByteF:\r
+ SHR ECX,1 ;Check even/odd\r
+ JNC NoWordF\r
+ STOSW ;Handle the odd word\r
+NoWordF:\r
+ REP STOSD ;Store FillCh in each DWORD\r
+ POP EBP\r
+ RETF 12 ;Pop args off the stack\r
+\r
+;===============================================\r
+; This routine does a NON case sensitive comparison of two strings up to\r
+; the length specified.\r
+; It returns -1 (0FFFFFFFFh) if all of the bytes are the same,\r
+; otherwise it returns the offset of the first error.\r
+;\r
+; CompareNCS(pS1, pS2, dSize) : returned offset or -1\r
+;\r
+; pS1 & pS2 pointer to strings to compare\r
+; dSize is length to compare out to\r
+;\r
+; Case is only ignored in the letters of the ASCII alphabet (A-Z).\r
+;\r
+; pS1 [EBP+20]\r
+; pS2 [EBP+16]\r
+; dSize [EBP+12]\r
+;\r
+PUBLIC __CompareNCS:\r
+ PUSH EBP ;Save calling frame\r
+ MOV EBP,ESP ;Set up my own frame pointer\r
+ MOV ESI, [EBP+20] ;Load address of String1\r
+ MOV EDI, [EBP+16] ;Load address of String2\r
+ MOV ECX, [EBP+12] ;Load count of bytes\r
+ CLD ;Set auto-increment\r
+CompNCS1:\r
+ REP CMPSB ;Compare strings...\r
+ JZ NCSMatch ;If all bytes ok, .. go for it\r
+NCSCase:\r
+ MOV AL,BYTE PTR [ESI-1] ;Get the p1 byte that failed\r
+ OR AL,20h ;Force it lower case\r
+ CMP AL,7Ah ;Greater than Little z ?\r
+ JG NCSNoGo ;If yes, Not character\r
+ CMP AL,61h ;Less than little a ?\r
+ JL NCSNoGo ;If yes, Not character\r
+ MOV BL,BYTE PTR [EDI-1] ;get the p2 byte that failed\r
+ OR BL,20h ;Force it lower case\r
+ CMP AL,BL\r
+ JNE NCSNoGo ;Still no match\r
+ JECXZ SHORT NCSMatch ;ECX=0 no chars left to check\r
+ JMP SHORT CompNCS1 ;Back to the top\r
+NCSNoGo:\r
+ MOV EAX, [EBP+12] ;Calc offset of bad byte\r
+ INC ECX ;Fix CX (DEC after LOOP)\r
+ SUB EAX,ECX ;Leave in AX for return value\r
+ JMP SHORT NCSDone\r
+NCSMatch:\r
+ MOV EAX, -1 ;Strings match\r
+NCSDone:\r
+ POP EBP ;Restore callers frame ptr\r
+ RETF 12 ;Pop args off the stack\r
+\r
+;===============================================\r
+; This routine does a CASE SENSITIVE comparison of two strings up to\r
+; the length specified.\r
+; It returns -1 (0FFFFFFFFh) if all of the bytes are the same,\r
+; otherwise it returns the offset of the first error.\r
+;\r
+; Compare(pS1, pS2, dSize) : returned offset or -1\r
+;\r
+; pDestination is begining address to fill\r
+; cBytes is the size of the fill area\r
+; bFill is the byte value to fill with\r
+;\r
+; pS1 [EBP+20]\r
+; pS2 [EBP+16]\r
+; dSize [EBP+12]\r
+;\r
+PUBLIC __Compare:\r
+ PUSH EBP ;Save calling frame\r
+ MOV EBP,ESP ;Set up my own frame pointer\r
+ MOV ESI, [EBP+20] ;Load address of String1\r
+ MOV EDI, [EBP+16] ;Load address of String2\r
+ MOV ECX, [EBP+12] ;Load count of bytes\r
+ CLD ;Set auto-increment\r
+ REP CMPSB ;Compare strings...\r
+ JZ CompMatch ;If all bytes ok, .. go for it\r
+ MOV EAX, [EBP+12] ;Calc offset of bad byte\r
+ INC ECX ;Fix CX (DEC after LOOP)\r
+ SUB EAX,ECX ;Leave in AX for return value\r
+ JMP SHORT CompDone\r
+CompMatch:\r
+ MOV EAX, -1 ;Strings match\r
+CompDone:\r
+ POP EBP ;Restore callers frame ptr\r
+ RETF 12 ;Pop args off the stack\r
+\r
+;=================== Module End ===============================\r