Amateur OS code



     Here I will post some code from time to time....

    Check for VGA,MCGA card....Sphinx C--
void Check_VGA()
{
$XOR BX,BX
$MOV AX,0x01A00
$INT 0x10
if(BL==0x80){
   SHOW("VGA card installed..\n");
$JMP CHECK_DONE
}
if(BL==0x0C){
   SHOW("MCGA card installed..\n");
$JMP CHECK_DONE
}
ELSE{ SHOW("MCGA or VGA not found..\n");
}
CHECK_DONE:
}

    Print text to screen....Sphinx C--
void SHOW()
{
/*
        Show a line of text passed in the AX on the screen...
*/
BH=0;
$PUSH SI
SI=AX;
AH=0xE;
UP:
$LODSB
$CMP AL,0
$JZ DOWN
$MOV BL,4
$INT 0x10
$JMP SHORT UP
DOWN:
$POP SI
}
    Note..This uses INT 0x10...It will only be used during bootup...
        I will soon post one that writes direct to memory..

    Set the a20 line...Inline HEX dump....
void a20_test()
{
/*
        Sets the A20 line...
        Returns AL=1
*/
$ DB 0XFA,0X31,0XC9,0XE4,0X64,0XA8,0X02,0XE0
$ DB 0XFA,0XB0,0XD1,0XE6,0X64,0XE4,0X64,0XA8
$ DB 0X02,0XE0,0XFA,0XB0,0XDF,0XE6,0X60,0XB9
$ DB 0X14,0X00,0XE7,0XED,0XE2,0XFC,0XFB,0XB0,0X01
}

    Test the a20 line...Inline HEX dump....
void test_a20()
{
/*
        Test the a20 line state...
        Return AL=0 for on
        AL=1 for off
*/
$ DB 0X31,0XC0,0X8E,0XE0,0X48,0X8E,0XE8,0X64
$ DB 0XA0,0X00,0X00,0X88,0XC4,0XF6,0XD0,0X65
$ DB 0X86,0X06,0X10,0X00,0X64,0X3A,0X26,0X00
$ DB 0X00,0X65,0XA2,0X10,0X00,0X74,0X05,0XB0
$ DB 0X01,0XE9,0X02,0X00,0XB0,0X00
}

    Read the command line
// Get the command line
$MOV AX,DS
$MOV ES,AX  //Point the es to the PSP
$XOR AX,AX
$MOV AL,ESBYTE[0x0080]
$MOV CommandLineLength,AX //Lenght of command line
$CMP CommandLineLength, 1
$JBE NO_CMD
CommandLinePos=1;  //Skip first space
MLOOP:
AX=CommandLinePos;
$MOV SI,AX
AX=CommandLineLength;
$CMP SI,AX
$JAE NO_CMD   //If we are at the end jump
if(ESWORD[SI+0x81]==0x682F){ //Look for /h
 $JMP HELP
}
if(ESBYTE[SI+0x81]==0x482F){ //Look for /H
 $JMP HELP
}
$INC CommandLinePos
$JMP MLOOP

    Convert LBA into CHS
void ConvertLBA_CHS()
{
/*
  Convert LBA in AX into CHS
 absolute sector = (logical sector / sectorpertrack)+1
 absolute head = (logical sector / sectorpertrack) MOD num heads
 absolute track= logical sector /(sectorpertrack * num heads)
*/
$XOR DX,DX  //Clear the dx
$DIV SectorsPerTrack //Divide AX by sectors per track
$INC DL   //Add 1
$MOV AbsoluteSector,DL
$XOR DX,DX  //Clear the dx
$DIV NumHeads;
$MOV AbsoluteHead,DL
$MOV AbsoluteTrack,AL
$RET
}

    Timer.C--            Download Timer.zip
/*
  Timer.C--
  An example of interrupt chaining using Sphinx C--
  Scott Billingsley 7,9,2001
*/
? include "WRITE.H--"

int count=0;
dword IntVectorSave=0

void HookVector()
{
/*
  Routine called on the interrupt.
  Aprox. 18 times a second.
*/
$PUSH SI                          //Save SI
DS=CS;
SI=#count;                         //SI equals the address of count
$ADD DSBYTE[SI],1       //Add 1 to count
$POP SI                            //Return SI
$JMP FAR IntVectorSave           //Turn control back to old ISR to keep
                                                    //the computer running right.
}                                                  //Old ISR does a return FAR back to program.

void main()
{
DS=CS;
$PUSH ES
$PUSH DI
$PUSH SI                          //Save the regiesters
AX=0;
ES=AX;                             //Set ES
$MOV EAX,ESDWORD[0x70]                      //Move a dword from the offset of the interrupt.
IntVectorSave=EAX;                                       //0x70 = 0x1C*4   , Save it
$PUSHF
$CLI                                                               //Turn off interrupts.
DI=0x70;                                                        //Offset for our routine.
AX=#HookVector                                          //Point AX to the address of out routine.
$STOSW                                                       //Store a word into the vector table
AX=CS;                                                         //Where out routine lives.
$STOSW                                                       //Store that too.
$POPF
$STI                                                               //Restore interrupts
$POP SI
$POP DI
$POP ES
SI=#count;
DSBYTE[SI]=0x00;                                      //Zero our count

do
{
DS=CS;                                                       //Reset the DS..Might change during the interrupt call
AH=1;
$INT 0x16                                                  //Check for a key press
if( NOTZEROFLAG ){
 $JMP END                                                 //If a key was pressed , exit
}
SI=#count;
AL=DSBYTE[SI];
if(AL==10){
 WRITESTR("Hello World!!\n");                  //If out cout is 10 print
 Si=#count;
 DSBYTE[SI]=0x00;                                   //Zero the count
}
}while(TRUE);                                              //Loop forever!!!

END:
$PUSH ES
AX=0x00;
ES=AX;   //Set ES
$PUSHF
$CLI                                                           //Turn off interrupts
EAX=IntVectorSave;
$MOV ESDWORD[0x70],EAX                  //Restore the old interrupt vector.
$POPF
$POP ES
$STI                                                           //Turn interrupts back on.

}