--- /dev/null
+;=============================================================================\r
+;\r
+; MMURTL IMAGE LOADER code:\r
+; Clears interrupts\r
+; Turn ON A20 adress line gate\r
+; Moves the OS data to 00000000 physical.\r
+; Moves the OS Code to 00010000 physical (64K Boundary)\r
+; Jumps to the OS Code entry point.\r
+; (This basically turns MS-DOS into a $79.00 loader)\r
+;\r
+;\r
+; We define the GDT and IDT entries in MOS.gdt and MOS.idt.\r
+;\r
+; NOTE: This the last the processor sees of 16 bit real mode code\r
+; (no great loss at all)\r
+;\r
+;=============================================================================\r
+\r
+LoadSeg SEGMENT USE16\r
+ ASSUME CS:LoadSeg, DS:Nothing, ES:Nothing, SS:Nothing\r
+\r
+IDTptr DW 7FFh ;LIMIT 256 IDT Slots\r
+ DD 0000h ;BASE (Linear)\r
+\r
+GDTptr DW (nGDTSlots*8)-1 ;LIMIT 768 GDT Slots\r
+ DD 0800h ;BASE (Linear)\r
+\r
+\r
+OSCodeSize EQU OSCodeEnd-OSCodeBegin\r
+OSCodeMore EQU OSCodeSize - 10000h\r
+OSDataSize EQU OSDataEnd-OSDataBegin\r
+\r
+\r
+\r
+START: CLI ; first we clear interrupts\r
+\r
+; Note: this next few lines of code turns on the address line 20 Gate!\r
+; This must be done before we can physically address above 1 Meg!\r
+\r
+ XOR CX,CX ;check 64K times\r
+IBEmm0:\r
+ IN AL,64h ;Read Status Byte into AL\r
+ TEST AL,02h ;Test The Input Buffer Full Bit\r
+ LOOPNZ IBEmm0\r
+ MOV AL,0D1h\r
+ OUT 64h,AL\r
+ XOR CX,CX ;check 64K times\r
+IBEmm1:\r
+ IN AL,64h ;Read Status Byte into AL\r
+ TEST AL,02h ;Test The Input Buffer Full Bit\r
+ LOOPNZ IBEmm1\r
+ MOV AL,0DFh\r
+ OUT 60h,AL\r
+ XOR CX,CX ;check 64K times\r
+IBEmm2:\r
+ IN AL,64h ;Read Status Byte into AL\r
+ TEST AL,02h ;Test The Input Buffer Full Bit\r
+ LOOPNZ IBEmm2\r
+\r
+; Move OS data to Physical Address 0000h\r
+\r
+ MOV AX,SEG OSDSeg ; Move Data segment to 0000h\r
+ MOV DS,AX ;\r
+ XOR SI,SI ; Source DS:SI\r
+ MOV AX,0000h ;\r
+ MOV ES,AX ;\r
+ XOR DI,DI ; Destination ES:DI\r
+ MOV ECX, OSDataSize+3 ;\r
+ CLD ;\r
+ REP MOVSB ;\r
+\r
+; Move OS Code to Physical Address 20000h (in 32K chunks)\r
+\r
+ MOV AX,SEG OSCSeg ; Move OS Code to 10000h\r
+ ADD AX, 1000h ; 10000h bytes into DOS segment\r
+ MOV DS,AX ;\r
+ XOR SI, SI ; Source DS:SI\r
+ MOV AX,1000h ; Segment 1000h (address 10000h)\r
+ MOV ES,AX ;\r
+ XOR DI,DI ; Destination ES:DI\r
+ MOV CX,8000h ; 64K Max (CODE is > 64K)\r
+ CLD ;\r
+ REP MOVSB ;\r
+\r
+ MOV AX,SEG OSCSeg ; Move OS Code to 10000h\r
+ ADD AX, 1800h ; 10000h bytes into DOS segment\r
+ MOV DS,AX ;\r
+ XOR SI, SI ; Source DS:SI\r
+ MOV AX,1800h ; Segment 1800h (address 18000h)\r
+ MOV ES,AX ;\r
+ XOR DI,DI ; Destination ES:DI\r
+ MOV CX,8000h ; 64K Max (CODE is > 64K)\r
+ CLD ;\r
+ REP MOVSB ;\r
+\r
+ MOV AX,SEG OSCSeg ; Move OS Code to 10000h\r
+ ADD AX, 2000h ;\r
+ MOV DS,AX ;\r
+ XOR SI, SI ; Source DS:SI\r
+ MOV AX,2000h ; Segment 1000h (address 10000h)\r
+ MOV ES,AX ;\r
+ XOR DI,DI ; Destination ES:DI\r
+ MOV CX, OSCodeMore+4;\r
+ CLD ;\r
+ REP MOVSB ;\r
+\r
+ LIDT CS:FWORD PTR IDTptr ; Load IDTR\r
+ LGDT CS:FWORD PTR GDTptr ; Load GDTR\r
+\r
+ MOV EAX,CR0 ; Set Protected Mode BIT\r
+ OR AL,1 ;\r
+ MOV CR0,EAX ;\r
+\r
+ JMP Next ; Clear Instruction Prefetch Queue\r
+Next:\r
+ MOV BX,DataSel ; Setup Data Selectors\r
+ MOV DS,BX ; D Selector\r
+ MOV ES,BX ; E Selector\r
+ MOV FS,BX ; F Selector\r
+ MOV GS,BX ; G Selector\r
+ MOV SS,BX ; S Selector\r
+;\r
+; PROTECTED MODE FAR JUMP TO 8:Offset OS code\r
+;\r
+ DB 066h ; 32 bit Data prefix\r
+ DB 067h ; 32 bit Address instruction prefix\r
+ DB 0EAh ; far jump opcode\r
+ DD OFFSET OSInitBegin ; 32 bit Offset ( Code Offset )\r
+ DW OSCodeSel ; 16 bit Selector ( Code Selector )\r
+\r
+LoadSeg ENDS\r
+\r
+ END START\r