/* 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(); } }