/* needs to stay the first line */
asm(".code16gcc;"
"jmp $0, $main");
/*
* 0 black
* 1 blue
* 2 green
* 3 cyan
* 4 red
* 5 magenta
* 6 brown
* 7 light gray
* 8 dark gray
* 9 light blue
* A light green
* B light cyan
* C light red
* D light magenta
* E yellow
* F white
*/
#define BG_COLOR 0x0
#define FG_COLOR 0x4
#define TEXT_COLOR (BG_COLOR << 4 | FG_COLOR)
void putc(char c) {
asm volatile("mov $0x0E, %%ah;"
"int $0x10;" ::"al"(c));
}
void putc_color(char c, char color) {
asm volatile("mov $0x09, %%ah;" // using Int 10h AH=09 for attributes
"and $0x00FF, %%bx;" // erase higher bits of bx
"mov $0x0001, %%cx;" // write the char once
"int $0x10;" // we need to manually move the cursor
"mov $0x0300, %%eax;" // get cursor position
"int $0x10;"
"add $0x1, %%dl;" // raise column by one
"mov $0x0200, %%eax;" // set cursor position
"int $0x10;" ::"al"(c),
"bl"(color)
: "cx", "dx");
}
void print(char const *const str) {
for (int i = 0; str[i] != '\0'; ++i) {
putc_color(str[i], TEXT_COLOR);
}
}
void new_line() {
putc('\n');
putc('\r');
}
char getc() {
char ret;
asm volatile(
".no_key:"
"xor %%eax, %%eax;"
"mov $0x0100, %%ax;" // check for keystroke:
"int $0x16;" // http://www.ctyme.com/intr/rb-1755.htm
"jz .no_key;" // wait for a key
".done:"
"xor %%eax, %%eax;"
"mov $0x1000, %%ax;" // get keystroke: http://www.ctyme.com/intr/rb-1754.htm
"int $0x16;"
"mov %%al, %%bl;" // temp store char in bl
"mov $0400, %%ax;" // clear keyboard buffer:
"int $0x16;" // http://www.ctyme.com/intr/rb-1759.htm
: "=b"(ret)
:
: "eax");
return ret;
}
void sleep(long ys) {
// http://www.ctyme.com/intr/rb-1525.htm : Int 15/AH=86h bios wait
asm volatile("mov $0x8600, %%ax;"
"int $0x15;" ::"cx"((ys >> 16)),
"dx"(ys));
}
void main(void) {
print("Hello!");
new_line();
asm volatile("mov $0x00A2, %%ax;" // switch to video mode
"int $0x10" ::
: "ax");
while (1) {
char buf[9];
for (unsigned char i = 0; i < 8; i++) {
char c = getc();
if (c == '\r') {
if (i == 0) { // empty entry
print("Reboot!");
sleep(500000); // sleep 500ms, to see the reboot print out, even if
// short
asm volatile(
"cli;" // disable interrupts
"mov $0x0FE, %%al;" // tell the keyboard controller to...
"out %%al, $0x64;" // ...activate the CPU reset line
".halt:"
"hlt;" // some motherboards require this
"jmp .halt;" :: // and again, just to be sure
: "al");
} else {
break;
}
}
buf[i] = c;
buf[i + 1] = 0;
putc_color('*', 0x02); // hard coded green on black
}
while (getc() != '\r')
;
new_line();
print(buf);
new_line();
}
}