###############################################################
# bochsrc.txt file for DLX Linux disk image.
###############################################################
# how much memory the emulated machine will have
megs: 1024
# filename of ROM images
romimage: file=./BIOS-bochs-latest
vgaromimage: file=./VGABIOS-lgpl-latest
# what disk images will be used
floppya: 1_44=a.img, status=inserted
floppyb: 1_44=floppyb.img, status=inserted
# hard disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="c.img", cylinders=60, heads=16, spt=63
# choose the boot disk.
boot: c #floppy
# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx
#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga
# where do we send log messages?
# log: bochsout.txt
# disable the mouse, since DLX is text only
mouse: enabled=0
# set up IPS value and clock sync
cpu: ips=15000000
clock: sync=both
# enable key mapping, using US layout as default.
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so
# in the DLX Linux example I'm enabling keyboard_mapping so that paste
# will work. Cut&Paste is currently implemented on win32 and X windows only.
keyboard: keymap=./x11-pc-us.map
#keyboard: keymap=../keymaps/x11-pc-fr.map
#keyboard: keymap=../keymaps/x11-pc-de.map
#keyboard: keymap=../keymaps/x11-pc-es.map
; boot.asm
bits 16
start16:
mov ax, 0x7c0
mov ds, ax
mov ss, ax
mov sp, 0
mov ax, 0xb800
mov es, ax
xor bx, bx
mov byte [es:bx], 'R'
inc bx
mov byte [es:bx], 0xc
inc bx
mov al, 18
mov dx, 0x1f2
out dx, al
mov al, 1
mov dx, 0x1f3
out dx, al
mov al, 0
mov dx, 0x1f4
out dx, al
mov al, 0
mov dx, 0x1f5
out dx, al
mov al, 1110_0000b
mov dx, 0x1f6
out dx, al
mov al, 0x20
mov dx, 0x1f7
out dx, al
mov dx, 0x1f7
.1:
in al, dx
and al, 1000_1000b
cmp al, 0000_1000b
jne .1
mov cx, 20 * 256
mov bx, 0x200
mov dx, 0x1f0
.2:
in ax, dx
mov [bx], ax
inc bx
inc bx
loop .2
mov ax, 0x7c0
mov ds, ax
mov ax, 0x50
mov es, ax
mov dword [0], 0
xor ebx, ebx
mov edx, 'PAMS'
mov di, 0
.4:
mov eax, 0xe820
mov ecx, 20
int 0x15
jc .5
add di, cx
inc dword [0]
cmp ebx, 0
jnz .4
jmp .6
.5:
jmp $
.6:
cli
mov ax, 0x7c0
mov ds, ax
mov es, ax
lgdt [gdtr]
mov eax, cr0
or eax, 0000_0000_0000_0000_0000_0000_0000_0001b
mov cr0, eax
mov ax, 1 * 8
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov esp, 36 * 512
mov ax, 3 * 8
mov gs, ax
jmp dword 2 * 8: 0
gdtr:
dw gdt_end - gdt_begin - 1
dd gdt_begin + 0x7c00
gdt_begin:
dq 0x0000_0000_0000_0000 ; 0 * 8
dq 0x00cf_9200_7e00_07ff ; 1 * 8
dq 0x00cf_9a00_7e00_07ff ; 2 * 8
dq 0x00cf_920b_8000_1000 ; 3 * 8
dq 0x00cf_9200_0000_ffff ; 4 * 8
gdt_end:
times 512 - 2 - ($ - $$) db 0
dw 0xaa55
kauto.cmd
nasm -fbin -o boot.bin boot.asm
nasm -fbin -o loader.bin loader.asm
ld -Ttext 0xc0101000 -o kernel.pe kernel.o lib.o
objcopy -I pe-i386 -O elf32-i386 kernel.pe
move kernel.pe kernel.elf32
kbulid.cmd
dd if=boot.bin of=c.img seek=0 count=1
dd if=loader.bin of=c.img seek=1 count=18
dd if=kernel.elf32 of=c.img seek=19 count=2048
// kernel.c
typedef struct ards {
int baseAddrLow;
int baseAddrHigh;
int lengthLow;
int lengthHigh;
short type;
}ards;
unsigned int* page_table_point;
unsigned int pos = 0;
struct crt_data {
char data[3];
};
struct crt_data crt_data = {0, 0, 0};
typedef enum {
false = 0, true = 1
}bool;
#define out(port, data) asm volatile ("out %w1, %b0;"::"a"(data), "d"(port))
#define in(port) ({\
unsigned char _res;\
asm volatile("in %b1, %w2":"=a"(_res):"0"(_res), "d"(port));\
_res;\
})
#define bcd2bin(data) ((data) = (((data)&0xf) + (((data)>>4)*10)))
#define sti() asm volatile ("sti");
#define cli() asm volatile ("cli");
void general(void);
void page_error(void);
void init_page(void);
void rtc_interrupt(void);
void init_8259(void);
void init_rtc(void);
void put_char(char c);
void put_s(char* s);
char* kprintf(char* s, ...);
char* itoa(unsigned int i,unsigned int n);
unsigned int strlen(char* s);
unsigned int div(unsigned int* i,unsigned int n);
void cls(void);
void getArdsCount(void);
void put_s_pos(char* s, unsigned int pos, unsigned int colour);
void load_sector(int start_sector, int sector_number, int start_memory);
void create_descriptor(int descriptor_table_address,
int selector, int base_address, int limit, int attrib);
void create_gate(int descriptor_table_address,
int number, int attrib, int selector, int offset);
void exception(void);
void panic_snail(const char* filename, const char* func, int line, const char* exp);
#define assert_snail(exp) if(!(exp)) panic_snail(__FILE__, __func__, __LINE__, #exp); \
else ;
unsigned int get_max(unsigned int* array, unsigned int length);
bool bit_match(unsigned int* v32, unsigned int p);
unsigned int map_search_block(unsigned int* v32, unsigned int map_l,
unsigned int block_l);
void set_0(unsigned int* v32, unsigned int p);
void set_1(unsigned int* v32, unsigned int p);
int mapOnePage(unsigned int virAddr, unsigned int phyAddr, unsigned int pageAttrib);
void kernel_entry(void) {
cls();
init_page();
int i;
for(i = 0; i < 32; i++) {
create_gate(0x1000 + 0xc0000000, i, 2 * 8, 0x8e00, (int)exception);
}
// put_s(kprintf("Hello, World!\n"));
// while(1);
create_gate(0x1000 + 0xc0000000, 13, 2 * 8, 0x8e00, (int)general);
create_gate(0x1000 + 0xc0000000, 14, 2 * 8, 0x8e00, (int)page_error);
create_gate(0x1000 + 0xc0000000, 0x28, 2 * 8, 0x8e00, (int)rtc_interrupt);
ards* pArds = (ards*)(0x500 + 0xc0000000);
int array[64] ;
int* parray = (void*)(0);
for(i = 0; i < *((int*)(0x7c00 + 0xc0000000)); i++, pArds++) {
put_s(kprintf("baseAddrLow = %x lengthLow = %x type = %d \n",
pArds->baseAddrLow, pArds->lengthLow, pArds->type));
array[i] = pArds->lengthLow;
}
// put_s(kprintf("\n%dM\n", get_max(parray, *((int*)(0x7c00 + 0xc0000000)) ) /1024/1024));
asm volatile ("mov word ptr [0x7c04 + 0xc0000000], 256 * 8 - 1;\
mov dword ptr [0x7c06 + 0xc0000000], 0x1000 + 0xc0000000;\
lidt [0x7c04 + 0xc0000000];\
");
init_8259();
init_rtc();
out(0x21, 0xfb);
out(0xa1, 0xfe);
// while(1) {}
sti();
// assert_snail( i > 256);
unsigned int t[100];
t[0] = 0xffff0000;
put_s(kprintf("@@@ %d @@@", bit_match(t, 16)));
set_1(t, 1);
set_1(t, 2);
set_1(t, 3);
put_s(kprintf("\n %b \n", t[0]));
put_s(kprintf("\n %b \n", t[1]));
put_s(kprintf("\n %d \n", map_search_block(t, 100 * 32, 17)));
put_s(kprintf("\n %d \n", map_search_block(t, 100 * 32, 10)));
mapOnePage(0x100000, 0xc00000, 0x7);
int data[3];
while(1) {
data[0] = crt_data.data[0];
data[1] = crt_data.data[1];
data[2] = crt_data.data[2];
if(data[0] < 10) {
put_s_pos("0", 0 * 80 * 2 + 140, 0xc);
put_s_pos(kprintf("%d", bcd2bin(data[0])), 0 * 80 * 2 + 142, 0xc);
} else {
put_s_pos(kprintf("%d", bcd2bin(data[0])), 0 * 80 * 2 + 140, 0xc);
}
put_s_pos(":", 0 * 80 * 2 + 144, 0xc);
if(data[1] < 10) {
put_s_pos("0", 0 * 80 * 2 + 146, 0xc);
put_s_pos(kprintf("%d", bcd2bin(data[1])), 0 * 80 * 2 + 148, 0xc);
} else {
put_s_pos(kprintf("%d", bcd2bin(data[1])), 0 * 80 * 2 + 146, 0xc);
}
put_s_pos(":", 0 * 80 * 2 + 150, 0xc);
if(data[2] < 10) {
put_s_pos("0", 0 * 80 * 2 + 152, 0xc);
put_s_pos(kprintf("%d", bcd2bin(data[2])), 0 * 80 * 2 + 154, 0xc);
} else {
put_s_pos(kprintf("%d", bcd2bin(data[2])), 0 * 80 * 2 + 152, 0xc);
}
asm volatile ("hlt");
}
}
void init_8259(void) {
out(0x20, 0x11);
out(0xa0, 0x11);
out(0x21, 0x20);
out(0xa1, 0x28);
out(0x21, 0x4);
out(0xa1, 0x2);
out(0x21, 0x1);
out(0xa1, 0x1);
out(0x21, 0xff);
out(0xa1, 0xff);
}
void put_char(char c) {
if(pos >= 4000){
pos = 0;
}
if(c == '\n') {
pos = (pos / (2 * 80) + 1) * 2 * 80;
return;
}
asm volatile ("mov ebx, %0;\
mov byte ptr gs:[ebx], %b1; \
inc ebx; \
mov byte ptr gs:[ebx], 0xf; \
inc ebx; \
mov %0, ebx "::"m"(pos), "a"(c));
}
void put_s(char* s) {
while(*s) {
put_char(*s);
s++;
}
}
char* kprintf(char* s, ...) {
static char buf[0x400];
char buf1[0x40];
char* pbuf = buf;
void** args = (void**)&s;
args++;
char* p, *q = buf1;
unsigned int i, l;
while(*s) {
if(*s == '%'){
s++;
switch(*s) {
case '%':
s++;
break;
case 's':
case 'S':
s++;
p = (char*)*args++;
while(*p) {
*pbuf++ = *p++;
}
break;
case 'c':
case 'C':
s++;
i = (int)*args++;
*pbuf++ = i;
break;
case 'b':
case 'B':
s++;
i = (int)*args++;
p = itoa(i, 2);
q = buf1;
l = 32 - strlen(p);
for(i = 0;i < l; i++) {
*q++ = '0';
}
while(*p) {
*q++ = *p++;
}
*q = '\0';
q = buf1;
i = 0;
while(*q){
if((i != 0) && (i % 4 == 0)) {
*pbuf++ = '_';
}
*pbuf++ = *q++;
i++;
}
*pbuf++ = 'b';
break;
case 'd':
case 'D':
s++;
i = (int)*args++;
p = itoa(i, 10);
while(*p){
*pbuf++ = *p++;
}
break;
case 'x':
case 'X':
s++;
i = (int)*args++;
p = itoa(i, 16);
*pbuf++ = '0';
*pbuf++ = 'x';
l = 8 - strlen(p);
q = buf1;
for(i = 0;i < l; i++) {
*q++ = '0';
}
while(*p) {
*q++ = *p++;
}
*q = '\0';
q = buf1;
i = 0;
while(*q){
if((i != 0) && (i % 4 == 0)) {
*pbuf++ = '_';
}
*pbuf++ = *q++;
i++;
}
break;
default:
break;
}
} else {
*pbuf++ = *s++;
}
}
*pbuf = '\0';
return buf;
}
unsigned int div(unsigned int* i, unsigned int n) {
unsigned int r = *i % n;
*i /= n;
return r;
}
unsigned int strlen(char* s) {
unsigned int len = 0;
while(*s) {
len++;
s++;
}
return len;
}
char* itoa(unsigned int i, unsigned int n) {
char s[] = "0123456789abcdef";
char buf0[0x20];
char* pbuf = buf0;
static char buf1[0x20];
char* qbuf = buf1;
int j;
if(!i) {
*qbuf++ = '0';
*qbuf = '\0';
return buf1;
}
while(i) {
*pbuf++ = s[div(&i, n)];
}
*pbuf = '\0';
for(j = strlen(buf0) - 1; j >= 0; j--) {
*qbuf++ = *--pbuf;
}
*qbuf = '\0';
return buf1;
}
void cls(void) {
asm (".1: mov byte ptr gs:[ebx], ' '; \
inc ebx;\
mov byte ptr gs:[ebx], 0xf;\
inc ebx;\
loop .1 "\
::"b"(0),"c"(2000));
// while(1) {}
}
void getArdsCount(void) {
asm volatile ("mov bx, 4 * 8; \
mov ds, bx; \
mov es, bx; \
rep movsb; \
mov eax, dword ptr[0x7c00]; \
mov dword ptr[0x100000 + 0x400], eax; \
mov bx, 1 * 8; \
mov ds, bx;\
mov es, bx" \
::"c"(1024),"S"(0x7c00 + 512),"D"(0x100000) \
);
}
void put_s_pos(char* s, unsigned int pos , unsigned int colour) {
asm volatile ("\
mov ah, cl;\
w_loop: mov al, [%0];\
or al, al;\
jz exit;\
mov gs:[%1], ax;\
inc %1;\
inc %1;\
inc %0;\
jmp w_loop;\
exit: "\
::"S"(s),"b"(pos),"c"(colour));
}
void exception(void) {
put_s(kprintf("Exception...!"));
while(1) {}
}
void init_rtc(void) {
out(0x70, 0x8b);
out(0x71, 0x12);
out(0x70, 0xc);
in(0x71);
}
void rtc_handler(void) {
out(0x70, 4);
crt_data.data[0] = in(0x71);
out(0x70, 2);
crt_data.data[1] = in(0x71);
out(0x70, 0);
crt_data.data[2] = in(0x71);
out(0x70, 0xc);
in(0x71);
}
void init_page(void) {
int i;
long* dir_table_base = (long*) (0x400000);
long* page_table_base = (long*) (0x400000 + 0x1000);
/*
for(i = 0 ; i < 3; i++, dir_table_base++) {
*dir_table_base = 0x400000 + 0x1000 + 0x7 + i * 0x1000;
}
for(i = 0; i < 3 * 1024; i++, page_table_base++) {
*page_table_base = 0x0 + 0x7 + i * 0x1000;
}
*/
for(i = 0, dir_table_base += 0xc0000000 / 0x400000; i < 3; i++, dir_table_base++) {
*dir_table_base = 0x400000 + 0x1000 + 0x100000 + 0x7 + i * 0x1000;
}
// put_s(kprintf(" %x ", page_table_base));
// put_s(kprintf(" %x ",--dir_table_base));
page_table_base = (long*)(0x400000 + 0x1000 + 0x100000);
for(i = 0; i < 3 * 1024; i++, page_table_base++) {
*page_table_base = 0x0 + 0x7 + i * 0x1000;
}
dir_table_base = (long*) (0xc0400000);
page_table_base = (long*) (0xc0400000 + 0x1000);
for(i = 0 ; i < 3; i++, dir_table_base++) {
*dir_table_base = 0x0;
}
for(i = 0; i < 3 * 1024; i++, page_table_base++) {
*page_table_base = 0x0;
}
asm volatile ("\
mov eax, 0x400000;\
mov cr3, eax;\
mov eax, cr0;\
or eax, 0x80000000;\
mov cr0, eax;\
jmp 1f;\
1:"\
);
}
void general(void) {
put_s(kprintf("General...!"));
while(1) {}
}
void page_error(void) {
put_s(kprintf("Page Error...!"));
while(1) {}
}
void panic_snail(const char* filename, const char* func, int line, const char* exp) {
cli();
put_s(kprintf("System Error...!\n""FileName is [%s]\n", filename));
put_s(kprintf("Func is [%s]\n", func));
put_s(kprintf("In [%d] Line\n", line));
put_s(kprintf("Condition is [%s]\n", exp));
while(1);
}
unsigned int get_max(unsigned int* array, unsigned int length) {
assert_snail(array);
int i;
unsigned int t;
for(i = 0, t = array[i]; i < length - 1; i++) {
if(t < array[i + 1]) {
t = array[i + 1];
}
}
return t;
}
bool bit_match(unsigned int* v32, unsigned int p) {
assert_snail(v32);
return (v32[p / 32] & (1 << (p % 32)))?true:false;
}
unsigned int map_search_block(unsigned int* v32, unsigned int map_l, unsigned int block_l) {
unsigned int i, c;
for(i = 0; i < map_l; i++) {
if(!(bit_match(v32, i))) {
break;
}
}
c = 0;
while(i < map_l) {
if(c == block_l) {
break;
}
if(!(bit_match(v32, i))) {
c++;
} else {
c = 0;
}
i++;
}
return i - block_l;
}
void set_0(unsigned int* v32, unsigned int p) {
if(bit_match(v32, p)) {
v32[p / 32] &= ~(1 << (p % 32));
}
}
void set_1(unsigned int* v32, unsigned int p) {
if(!(bit_match(v32, p))) {
v32[p / 32] |= 1 << (p % 32);
}
}
int mapOnePage(unsigned int virAddr, unsigned int phyAddr, unsigned int pageAttrib) {
unsigned int pageDirBase = 0xc0400000, pageTableBase = 0xc0400000 + 0x1000;
*(unsigned int*)(pageDirBase + virAddr / 0x400000 * 4) = (0x400000 + 0x1000 + virAddr / 0x1000 * 4) + pageAttrib;
*(unsigned int*)(pageTableBase + virAddr / 0x1000 * 4) = phyAddr + pageAttrib;
}
; lib.asm
global _create_gate, _load_sector, _create_descriptor
; void load_sector(int start_sector, int sector_number, int start_memory)
; mov dword [esp + 0 * 4], START_SECTOR
; mov dword [esp + 1 * 4], SECTOR_NUMBER
; mov dword [esp + 2 * 4], START_MEMORY
; call load_sector
_load_sector:
push ebp
mov ebp, esp
pusha
mov esi, [ebp + 2 * 4]
mov edi, [ebp + 3 * 4]
mov ebx, [ebp + 4 * 4]
.3:
mov al, 1
mov dx, 0x1f2
out dx, al
mov eax, esi
mov dx, 0x1f3
out dx, al
shr eax, 8
mov dx, 0x1f4
out dx, al
shr eax, 8
mov dx, 0x1f5
out dx, al
shr eax, 8
and al, 0x0f
or al, 1110_0000b
mov dx, 0x1f6
out dx, al
mov al, 0x20
mov dx, 0x1f7
out dx, al
mov dx, 0x1f7
.1:
in al, dx
and al, 1000_1000b
cmp al, 0000_1000b
jne .1
mov ecx, 256
mov dx, 0x1f0
.2:
in ax, dx
mov [ebx], ax
inc ebx
inc ebx
loop .2
inc esi
dec edi
cmp edi, 0
jne .3
popa
leave
ret
; void create_descriptor(int descriptor_table_address, int selector, int base_address, int limit, int attrib)
; mov dword [esp + 0 * 4], DESCRIPTOR_TABLE_ADDRESS
; mov dword [esp + 1 * 4], SELECTOR
; mov dword [esp + 2 * 4], BASE_ADDRESS
; mov dword [esp + 3 * 4], LIMIT
; mov dword [esp + 4 * 4], ATTRIB
; call create_descriptor
_create_descriptor:
push ebp
mov ebp, esp
pusha
mov esi, [ebp + 2 * 4]
mov edi, [ebp + 3 * 4]
shl edi, 3
add edi, esi
mov ebx, [ebp + 4 * 4]
mov [edi + 2], ebx
shr ebx, 28
mov [edi + 7], bl
mov ebx, [ebp + 5 * 4]
mov [edi + 0], bx
shr ebx, 16
mov [edi + 6], bl
mov eax, [ebp + 6 * 4]
mov [edi + 5], al
and ah, 0xf0
or [edi + 6], ah
popa
leave
ret
; void create_gate(int descriptor_table_address, int number, int attrib, int selector, int attrib)
; mov dword [esp + 0 * 4], DESCRIPTOR_TABLE_ADDRESS
; mov dword [esp + 1 * 4], NUMBER
; mov dword [esp + 2 * 4], ATTRIB
; mov dword [esp + 3 * 4],SELECTOR
; mov dword [esp + 4 * 4], OFFSET
; call create_gate
_create_gate:
push ebp
mov ebp, esp
pusha
mov ebx, [ebp + 2 * 4]
mov ecx, [ebp + 3 * 4]
shl ecx, 3
add ebx, ecx
mov ax, [ebp + 4 * 4]
mov [ebx + 2], ax
mov ax, [ebp + 5 * 4]
mov [ebx + 4], ax
mov eax, [ebp + 6 * 4]
mov [ebx + 0], ax
shr eax, 16
mov [ebx + 6], ax
popa
leave
ret
; void put_s_pos(char* s, int colour, int pos);
_put_s_pos:
push ebp
mov ebp, esp
mov esi, [ebp + 2 * 4]
mov ah, [ebp + 3 * 4]
mov ebx, [ebp + 4 * 4]
.1:
mov al, [esi]
or al, al
jz .2
mov [gs:ebx], ax
inc ebx
inc ebx
inc esi
jmp .1
.2:
leave
ret
global _rtc_interrupt
extern _rtc_handler
_rtc_interrupt:
pusha
push ds
push es
push fs
push gs
call _rtc_handler
mov al, 0x20
out 0x20, al
out 0xa0, al
pop gs
pop fs
pop es
pop ds
popa
iret
; loader.asm
bits 32
start32:
mov ebx, 1 * 2 * 80 + 0
mov byte [gs:ebx], 'P'
inc ebx
mov byte [gs:ebx], 0xe
inc ebx
; void load_sector(int start_sector, int sector_number, int start_memory)
mov dword [esp + 0 * 4], 19
mov dword [esp + 1 * 4], 2048
mov dword [esp + 2 * 4], 0x100000
call load_sector
; void create_descriptor(int descriptor_table_address, int selector, int base_address, int limit, int attrib)
mov dword [esp + 0 * 4], 0x10000
mov dword [esp + 1 * 4], 0
mov dword [esp + 2 * 4], 0x0
mov dword [esp + 3 * 4], 0x0
mov dword [esp + 4 * 4], 0x0
call create_descriptor
mov dword [esp + 0 * 4], 0x10000
mov dword [esp + 1 * 4], 1
mov dword [esp + 2 * 4], 0x0
mov dword [esp + 3 * 4], 0xfffff
mov dword [esp + 4 * 4], 0xcf00 + 0x92
call create_descriptor
mov dword [esp + 0 * 4], 0x10000
mov dword [esp + 1 * 4], 2
mov dword [esp + 2 * 4], 0x0
mov dword [esp + 3 * 4], 0xfffff
mov dword [esp + 4 * 4], 0xcf00 + 0x9a
call create_descriptor
mov dword [esp + 0 * 4], 0x10000
mov dword [esp + 1 * 4], 3
mov dword [esp + 2 * 4], 0xb8000 + 0xc000_0000
mov dword [esp + 3 * 4], 0xffffffff
mov dword [esp + 4 * 4], 0xcf00 + 0x92
call create_descriptor
lgdt [gdtr]
call setup_page
mov ax, 1 * 8
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov esp, 0xc000_0000 + 0x400000
mov ax, 3 * 8
mov gs, ax
jmp dword 2 * 8 : 0xc0101000
jmp $
gdtr:
dw 8192 * 8 - 1
dd 0xc001_0000
; void load_sector(int start_sector, int sector_number, int start_memory)
; mov dword [esp + 0 * 4], START_SECTOR
; mov dword [esp + 1 * 4], SECTOR_NUMBER
; mov dword [esp + 2 * 4], START_MEMORY
; call load_sector
load_sector:
push ebp
mov ebp, esp
pusha
push ds
mov ax, 4 * 8
mov ds, ax
mov esi, [ebp + 2 * 4]
mov edi, [ebp + 3 * 4]
mov ebx, [ebp + 4 * 4]
.3:
mov al, 1
mov dx, 0x1f2
out dx, al
mov eax, esi
mov dx, 0x1f3
out dx, al
shr eax, 8
mov dx, 0x1f4
out dx, al
shr eax, 8
mov dx, 0x1f5
out dx, al
shr eax, 8
and al, 0x0f
or al, 1110_0000b
mov dx, 0x1f6
out dx, al
mov al, 0x20
mov dx, 0x1f7
out dx, al
mov dx, 0x1f7
.1:
in al, dx
and al, 1000_1000b
cmp al, 0000_1000b
jne .1
mov ecx, 256
mov dx, 0x1f0
.2:
in ax, dx
mov [ebx], ax
inc ebx
inc ebx
loop .2
inc esi
dec edi
cmp edi, 0
jne .3
pop ds
popa
leave
ret
; void create_descriptor(int descriptor_table_address, int selector, int base_address, int limit, int attrib)
; mov dword [esp + 0 * 4], DESCRIPTOR_TABLE_ADDRESS
; mov dword [esp + 1 * 4], SELECTOR
; mov dword [esp + 2 * 4], BASE_ADDRESS
; mov dword [esp + 3 * 4], LIMIT
; mov dword [esp + 4 * 4], ATTRIB
; call create_descriptor
create_descriptor:
push ebp
mov ebp, esp
pusha
push ds
mov ax, 4 * 8
mov ds, ax
mov esi, [ebp + 2 * 4]
mov edi, [ebp + 3 * 4]
shl edi, 3
add edi, esi
mov ebx, [ebp + 4 * 4]
mov [edi + 2], ebx
shr ebx, 24
mov [edi + 7], bl
mov ebx, [ebp + 5 * 4]
mov [edi + 0], bx
shr ebx, 16
mov [edi + 6], bl
mov eax, [ebp + 6 * 4]
mov [edi + 5], al
and ah, 0xf0
or [edi + 6], ah
pop ds
popa
leave
ret
; void create_gate(int descriptor_table_address, int number, int offset, int selector, int attrib)
; mov dword [esp + 0 * 4], DESCRIPTOR_TABLE_ADDRESS
; mov dword [esp + 1 * 4], NUMBER
; mov dword [esp + 2 * 4], OFFSET
; mov dword [esp + 3 * 4],SELECTOR
; mov dword [esp + 4 * 4], ATTRIB
; call create_gate
create_gate:
push ebp
mov ebp, esp
pusha
push ds
mov ax, 4 * 8
mov ds, ax
mov esi, [ebp + 2 * 4]
mov edi, [ebp + 3 * 4]
shl edi, 3
add edi, esi
mov ebx, [ebp + 4 * 4]
mov [edi + 0], ebx
mov [edi + 4], ebx
mov ebx, [ebp + 5 * 4]
mov [edi + 2], bx
mov eax, [ebp + 6 * 4]
mov [edi + 4], ax
pop ds
popa
leave
ret
; void setup_page(void)
setup_page:
push ebp
mov ebp, esp
pusha
mov ecx, 3
mov edi, 0x400000 - 0x7e00
mov eax, 0x400000 + 0x1000 + 0x7
.1: stosd
add eax, 0x1000
loop .1
mov ecx, 3 * 1024
mov edi, 0x400000 + 0x1000 - 0x7e00
mov eax, 0x0 + 0x7
.2: stosd
add eax, 0x1000
loop .2
mov ecx, 3
mov edi, 0x400000 + 0xc000_0000 / 0x400000 * 4 - 0x7e00
mov eax, 0x400000 + 0x4000 + 0x7
.3: stosd
add eax, 0x1000
loop .3
mov ecx, 3 * 1024
mov edi, 0x400000 + 0x4000 - 0x7e00
mov eax, 0x0 + 0x7
.4: stosd
add eax, 0x1000
loop .4
mov eax, 0x400000
mov cr3, eax
mov eax, cr0
or eax, 0x8000_0000
mov cr0, eax
jmp .5
.5:
popa
leave
ret
#Makefile
all: c2o s2o asm2o
kauto.cmd
build:
make all
kbuild.cmd
run: build
run.cmd
dbg: build
dbg.cmd
c2o: $(patsubst %.c, %.o, $(wildcard *.c))
%.o:%.c
gcc -masm=intel -c -o $@ $^
s2o: $(patsubst %.s, %.o, $(wildcard *.s))
%.o:%.s
gcc -masm=intel -c -o $@ $^
asm2o: $(patsubst %.asm, %.o, $(wildcard *.asm))
%.o:%.asm
nasm -felf -o $@ $^
clean:
del *.o *.bin *.pe *.elf32 *.lock
run.cmd
bochs -q -f bochsrc.bxrc
dbg.cmd
%dbg.cmd%
bochsdbg.exe -q -f bochsrc.bxrc