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.
}