[
  {
    "path": "README.md",
    "content": "539kernel is a simple x86 32bit educational kernel which has been written especially for the book \"**[A Journey in Creating an Operating System Kernel](https://539kernel.com)**\" which is available freely on <https://539kernel.com>.\n\n* `src/` contains the last version of 539kernel. \n* `evolution_by_versions/` contains the version of 539kernel while it's under development through the different chapters in the book.\n"
  },
  {
    "path": "evolution_by_versions/.gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/c\n# Edit at https://www.gitignore.io/?templates=c\n\n### C ###\n# Prerequisites\n*.d\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n*.bin\n\n# Linker output\n*.ilk\n*.map\n*.exp\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n*.su\n*.idb\n*.pdb\n\n# Kernel Module Compile Results\n*.mod*\n*.cmd\n.tmp_versions/\nmodules.order\nModule.symvers\nMkfile.old\ndkms.conf\n\n# End of https://www.gitignore.io/api/c\n\n*.img\n"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/Makefile",
    "content": "ASM = nasm\nBOOTSTRAP_FILE = bootstrap.asm \nKERNEL_FILE = simple_kernel.asm\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f bin $(KERNEL_FILE) -o kernel.o\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=kernel.o of=kernel.img bs=512\n\tqemu-system-x86_64 -s kernel.img\n\nclean:\n\trm -f *.o\n"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/bootstrap.asm",
    "content": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\tcall load_kernel_from_disk\n\tjmp 0900h:0000\n\t\nload_kernel_from_disk:\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h\n\tmov al, 01h\n\tmov ch, 0h\n\tmov cl, 02h\n\tmov dh, 0h\n\tmov dl, 80h\n\tmov bx, 0h\n\tint 13h\n\t\n\tjc kernel_load_error\n\n    ret\n    \nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\tjmp $\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\t\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; Reading current cursor position\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n    ; Move the cursor to the beginning\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n\n\tret\n\ntitle_string        db  'The Bootloader of 539kernel.', 0\nmessage_string      db  'The kernel is loading...', 0\nload_error_string   db  'The kernel cannot be loaded', 0\n\ntimes 510-($-$$) db 0\n\ndw 0xAA55\n"
  },
  {
    "path": "evolution_by_versions/01_539kernel_bootloader/simple_kernel.asm",
    "content": "start:\n\tmov ax, cs\n\tmov ds, ax\n\n\t; --- ;\n\t\n\tmov si, hello_string\n\tcall print_string\n\t\n\tjmp $\n\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje done\n\t\n\tint 10h\n\t\n\tjmp print_char\n\ndone:\n\tret\n\t\nhello_string db 'Hello World!, From Simple Assembly 539kernel!', 0\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/Makefile",
    "content": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie\nKERNEL_OBJECT = -o kernel.elf\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=5\n\tdd seek=6 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046\n\tqemu-system-x86_64 -s kernel.img\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/bootstrap.asm",
    "content": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\tcall load_kernel_from_disk\n\tjmp 0900h:0000\n\t\nload_kernel_from_disk:\n\tmov ax, [curr_sector_to_load]\n\tsub ax, 2\n\tmov bx, 512d\n\tmul bx\n\tmov bx, ax\n\t\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h\n\tmov al, 1h\n\tmov ch, 0h\n\tmov cl, [curr_sector_to_load]\n\tmov dh, 0h\n\tmov dl, 80h\n\tint 13h\n\t\t\n\tjc kernel_load_error\n\t\n\tsub byte [number_of_sectors_to_load], 1\n\tadd byte [curr_sector_to_load], 1\n\tcmp byte [number_of_sectors_to_load], 0\n\t\n\tjne load_kernel_from_disk\n\t\n\tret\n    \nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\tjmp $\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\t\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; Reading current cursor position\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n    ; Move the cursor to the beginning\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n\n\tret\n\ntitle_string        db  'The Bootloader of 539kernel.', 0\nmessage_string      db  'The kernel is loading...', 0\nload_error_string   db  'The kernel cannot be loaded', 0\nnumber_of_sectors_to_load \tdb \t10d\ncurr_sector_to_load \t\tdb \t2d\n\ntimes 510-($-$$) db 0\n\ndw 0xAA55\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/gdt.asm",
    "content": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9200, 0x00cf\n\tuserspace_code_descriptor\t: \tdw 0xffff, 0x0000, 0xfa00, 0x00cf\n\tuserspace_data_descriptor\t: \tdw 0xffff, 0x0000, 0xf200, 0x00cf\n\ngdtr:\n\tgdt_size_in_bytes\t: \tdw ( 5 * 8 )\n\tgdt_base_address\t: \tdd gdt\n\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/idt.asm",
    "content": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcli\n\tpush 3\n\tjmp isr_basic\n\t\nisr_4:\n\tcli\n\tpush 4\n\tjmp isr_basic\n\t\nisr_5:\n\tcli\n\tpush 5\n\tjmp isr_basic\n\t\nisr_6:\n\tcli\n\tpush 6\n\tjmp isr_basic\n\t\nisr_7:\n\tcli\n\tpush 7\n\tjmp isr_basic\n\t\nisr_8:\n\tcli\n\tpush 8\n\tjmp isr_basic\n\t\nisr_9:\n\tcli\n\tpush 9\n\tjmp isr_basic\n\t\nisr_10:\n\tcli\n\tpush 10\n\tjmp isr_basic\n\t\nisr_11:\n\tcli\n\tpush 11\n\tjmp isr_basic\n\t\nisr_12:\n\tcli\n\tpush 12\n\tjmp isr_basic\n\t\nisr_13:\n\tcli\n\tpush 13\n\tjmp isr_basic\n\t\nisr_14:\n\tcli\n\tpush 14\n\tjmp isr_basic\n\t\nisr_15:\n\tcli\n\tpush 15\n\tjmp isr_basic\n\t\nisr_16:\n\tcli\n\tpush 16\n\tjmp isr_basic\n\t\nisr_17:\n\tcli\n\tpush 17\n\tjmp isr_basic\n\t\nisr_18:\n\tcli\n\tpush 18\n\tjmp isr_basic\n\t\nisr_19:\n\tcli\n\tpush 19\n\tjmp isr_basic\n\t\nisr_20:\n\tcli\n\tpush 20\n\tjmp isr_basic\n\t\nisr_21:\n\tcli\n\tpush 21\n\tjmp isr_basic\n\nisr_22:\n\tcli\n\tpush 22\n\tjmp isr_basic\n\t\nisr_23:\n\tcli\n\tpush 23\n\tjmp isr_basic\n\t\nisr_24:\n\tcli\n\tpush 24\n\tjmp isr_basic\n\t\nisr_25:\n\tcli\n\tpush 25\n\tjmp isr_basic\n\t\nisr_26:\n\tcli\n\tpush 26\n\tjmp isr_basic\n\t\nisr_27:\n\tcli\n\tpush 27\n\tjmp isr_basic\n\t\nisr_28:\n\tcli\n\tpush 28\n\tjmp isr_basic\n\t\nisr_29:\n\tcli\n\tpush 29\n\tjmp isr_basic\n\t\nisr_30:\n\tcli\n\tpush 30\n\tjmp isr_basic\n\t\nisr_31:\n\tcli\n\tpush 31\n\tjmp isr_basic\n\t\nisr_32:\n\tcli\n\tpush 32\n\tjmp irq_basic\n\t\nisr_33:\n\tcli\n\tpush 33\n\tjmp irq_basic\n\t\nisr_34:\n\tcli\n\tpush 34\n\tjmp irq_basic\n\t\nisr_35:\n\tcli\n\tpush 35\n\tjmp irq_basic\n\t\nisr_36:\n\tcli\n\tpush 36\n\tjmp irq_basic\n\t\nisr_37:\n\tcli\n\tpush 37\n\tjmp irq_basic\n\nisr_38:\n\tcli\n\tpush 38\n\tjmp irq_basic\n\nisr_39:\n\tcli\n\tpush 39\n\tjmp irq_basic\n\nisr_40:\n\tcli\n\tpush 40\n\tjmp irq_basic\n\nisr_41:\n\tcli\n\tpush 41\n\tjmp irq_basic\n\nisr_42:\n\tcli\n\tpush 42\n\tjmp irq_basic\n\nisr_43:\n\tcli\n\tpush 43\n\tjmp irq_basic\n\nisr_44:\n\tcli\n\tpush 44\n\tjmp irq_basic\n\nisr_45:\n\tcli\n\tpush 45\n\tjmp irq_basic\n\nisr_46:\n\tcli\n\tpush 46\n\tjmp irq_basic\n\nisr_47:\n\tcli\n\tpush 47\n\tjmp irq_basic\n\t\nisr_48:\n\tcli\n\tpush 48\n\tjmp irq_basic\n\t\nisr_basic:\n\tcall interrupt_handler\n\t\n\tpop eax\n    \n    sti\n\tiret\n\t\nirq_basic:\n\tcall interrupt_handler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tcmp byte [esp], 40d\n\tjnge irq_basic_end\n\t\n\tmov al, 0xa0\n\tout 0x20, al\n\t\n\tirq_basic_end:\n\t\tpop eax\n        \n        sti\n\t\tiret\n\t\t\nidt:\n\tdw isr_0, 8, 0x8e00, 0x0000\n\tdw isr_1, 8, 0x8e00, 0x0000\n\tdw isr_2, 8, 0x8e00, 0x0000\n\tdw isr_3, 8, 0x8e00, 0x0000\n\tdw isr_4, 8, 0x8e00, 0x0000\n\tdw isr_5, 8, 0x8e00, 0x0000\n\tdw isr_6, 8, 0x8e00, 0x0000\n\tdw isr_7, 8, 0x8e00, 0x0000\n\tdw isr_8, 8, 0x8e00, 0x0000\n\tdw isr_9, 8, 0x8e00, 0x0000\n\tdw isr_10, 8, 0x8e00, 0x0000\n\tdw isr_11, 8, 0x8e00, 0x0000\n\tdw isr_12, 8, 0x8e00, 0x0000\n\tdw isr_13, 8, 0x8e00, 0x0000\n\tdw isr_14, 8, 0x8e00, 0x0000\n\tdw isr_15, 8, 0x8e00, 0x0000\n\tdw isr_16, 8, 0x8e00, 0x0000\n\tdw isr_17, 8, 0x8e00, 0x0000\n\tdw isr_18, 8, 0x8e00, 0x0000\n\tdw isr_19, 8, 0x8e00, 0x0000\n\tdw isr_20, 8, 0x8e00, 0x0000\n\tdw isr_21, 8, 0x8e00, 0x0000\n\tdw isr_22, 8, 0x8e00, 0x0000\n\tdw isr_23, 8, 0x8e00, 0x0000\n\tdw isr_24, 8, 0x8e00, 0x0000\n\tdw isr_25, 8, 0x8e00, 0x0000\n\tdw isr_26, 8, 0x8e00, 0x0000\n\tdw isr_27, 8, 0x8e00, 0x0000\n\tdw isr_28, 8, 0x8e00, 0x0000\n\tdw isr_29, 8, 0x8e00, 0x0000\n\tdw isr_30, 8, 0x8e00, 0x0000\n\tdw isr_31, 8, 0x8e00, 0x0000\n\tdw isr_32, 8, 0x8e00, 0x0000\n\tdw isr_33, 8, 0x8e00, 0x0000\n\tdw isr_34, 8, 0x8e00, 0x0000\n\tdw isr_35, 8, 0x8e00, 0x0000\n\tdw isr_36, 8, 0x8e00, 0x0000\n\tdw isr_37, 8, 0x8e00, 0x0000\n\tdw isr_38, 8, 0x8e00, 0x0000\n\tdw isr_39, 8, 0x8e00, 0x0000\n\tdw isr_40, 8, 0x8e00, 0x0000\n\tdw isr_41, 8, 0x8e00, 0x0000\n\tdw isr_42, 8, 0x8e00, 0x0000\n\tdw isr_43, 8, 0x8e00, 0x0000\n\tdw isr_44, 8, 0x8e00, 0x0000\n\tdw isr_45, 8, 0x8e00, 0x0000\n\tdw isr_46, 8, 0x8e00, 0x0000\n\tdw isr_47, 8, 0x8e00, 0x0000\n\tdw isr_48, 8, 0x8e00, 0x0000\n\t\nidtr:\n\tidt_size_in_bytes\t: \tdw idtr - idt\n\tidt_base_address\t: \tdd idt\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/linker.ld",
    "content": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {\n    code = .; _code = .; __code = .;\n    *(.text)\n  }\n\n  .data :\n  {\n     data = .; _data = .; __data = .;\n     *(.data)\n     *(.rodata)\n  }\n\n  .bss :\n  {\n    bss = .; _bss = .; __bss = .;\n    *(.bss)\n  }\n\n  end = .; _end = .; __end = .;\n} \n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/main.c",
    "content": "volatile unsigned char *video = 0xB8000;\n\nint nextTextPos = 0;\nint currLine = 0;\n\nvoid print( char * );\nvoid println();\nvoid printi( int );\n\nvoid kernel_main()\n{\n\tprint( \"Welcome to 539kernel!\" );\n\tprintln();\n\tprint( \"We are now in Protected-mode\" );\n\tprintln();\n\tprinti( 539 );\n\tprintln();\n\t\n\twhile( 1 );\n}\n\nvoid interrupt_handler( int interrupt_number )\n{\n\tprintln();\n\tprint( \"Interrupt Received \" );\n\tprinti( interrupt_number );\n}\n\nvoid print( char *str )\n{\n\tint currCharLocationInVidMem, currColorLocationInVidMem;\n\t\n\twhile ( *str != '\\0' )\n\t{\n        currCharLocationInVidMem = nextTextPos * 2;\n\t\tcurrColorLocationInVidMem = currCharLocationInVidMem + 1;\n\t\t\n\t\tvideo[ currCharLocationInVidMem ] = *str;\n\t\tvideo[ currColorLocationInVidMem ] = 15;\n\t\t\n\t\tnextTextPos++;\n\t\t\n\t\tstr++;\n\t}\n}\n\nvoid println()\n{\n\tnextTextPos = ++currLine * 80;\n}\n\nvoid printi( int number )\n{\n\tchar* digitToStr[] = { \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" };\n\t\n\tif ( number >= 0 && number <= 9 )\n\t{\n\t\tprint( digitToStr[ number ] );\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tint remaining = number % 10;\n\t\tnumber = number / 10;\n\t\t\n\t\tprinti( number );\n\t\tprinti( remaining );\n\t}\n}\n"
  },
  {
    "path": "evolution_by_versions/03_539kernel_progenitor/starter.asm",
    "content": "bits 16\nextern kernel_main\nextern interrupt_handler\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\tcall load_gdt\n\tcall init_video_mode\n\tcall enter_protected_mode\n    call setup_interrupts\n\t\n\tcall 08h:start_kernel\n\t\nload_gdt:\n\tcli\n\tlgdt [gdtr - start]\n\t\n\tret\n\t\nenter_protected_mode:\n\tmov eax, cr0\n\tor eax, 1\n\tmov cr0, eax\n\t\n\tret\n\t\ninit_video_mode:\n\tmov ah, 0h\n\tmov al, 03h\n\tint 10h\n\t\n\tmov ah, 01h\n\tmov cx, 2000h\n\tint 10h\n\t\n\tret\n\t\nsetup_interrupts:\n\tcall remap_pic\n\tcall load_idt\n\t\n\tret\n\t\nremap_pic:\n\tmov al, 11h\n\t\n\tsend_init_cmd_to_pic_master: \t\n\t\tout 0x20, al\n\t\t\n\tsend_init_cmd_to_pic_slave: \t\n\t\tout 0xa0, al\n\t\t\n\t; ... ;\n\t\n\tmake_irq_starts_from_intr_32_in_pic_master:\t\t\n\t\tmov al, 32d\n\t\tout 0x21, al\n\t\n\tmake_irq_starts_from_intr_40_in_pic_slave:\n\t\tmov al, 40d\n\t\tout 0xa1, al \n\t\n\t; ... ;\n\t\n\ttell_pic_master_where_pic_slave_is_connected:\n\t\tmov al, 04h\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_where_pic_master_is_connected:\n\t\tmov al, 02h\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 01h\n\t\n\ttell_pic_master_the_arch_is_x86:\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_the_arch_is_x86:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 0h\n\t\n\tmake_pic_master_enables_all_irqs:\n\t\tout 0x21, al\n\t\n\tmake_pic_slave_enables_all_irqs:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tret\n\t\nload_idt:\n\tlidt [idtr - start]\n\tret\n\t\nbits 32\nstart_kernel:\n\tmov eax, 10h\n\tmov ds, eax\n\tmov ss, eax\n    \n\tmov eax, 0h\n\tmov es, eax\n\tmov fs, eax\n\tmov gs, eax\n\t\n\tsti\n\t\n\tcall kernel_main\n\t\n%include \"gdt.asm\"\n%include \"idt.asm\"\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/Makefile",
    "content": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie\nKERNEL_OBJECT = -o kernel.elf\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\t$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf\n\t$(CC) $(KERNEL_FLAGS) process.c -o process.elf\n\t$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=8\n\tdd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046\n\tqemu-system-x86_64 -s kernel.img\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/bootstrap.asm",
    "content": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\tcall load_kernel_from_disk\n\tjmp 0900h:0000\n\t\nload_kernel_from_disk:\n\tmov ax, [curr_sector_to_load]\n\tsub ax, 2\n\tmov bx, 512d\n\tmul bx\n\tmov bx, ax\n\t\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h\n\tmov al, 1h\n\tmov ch, 0h\n\tmov cl, [curr_sector_to_load]\n\tmov dh, 0h\n\tmov dl, 80h\n\tint 13h\n\t\t\n\tjc kernel_load_error\n\t\n\tsub byte [number_of_sectors_to_load], 1\n\tadd byte [curr_sector_to_load], 1\n\tcmp byte [number_of_sectors_to_load], 0\n\t\n\tjne load_kernel_from_disk\n\t\n\tret\n    \nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\tjmp $\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\t\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; Reading current cursor position\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n    ; Move the cursor to the beginning\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n\n\tret\n\ntitle_string        db  'The Bootloader of 539kernel.', 0\nmessage_string      db  'The kernel is loading...', 0\nload_error_string   db  'The kernel cannot be loaded', 0\nnumber_of_sectors_to_load \tdb \t10d\ncurr_sector_to_load \t\tdb \t2d\n\ntimes 510-($-$$) db 0\n\ndw 0xAA55\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/gdt.asm",
    "content": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9200, 0x00cf\n\tuserspace_code_descriptor\t: \tdw 0xffff, 0x0000, 0xfa00, 0x00cf\n\tuserspace_data_descriptor\t: \tdw 0xffff, 0x0000, 0xf200, 0x00cf\n\ttss_descriptor\t\t\t\t: \tdw tss + 3, tss, 0x8900, 0x0000\n\ngdtr:\n\tgdt_size_in_bytes\t: \tdw ( 6 * 8 )\n\tgdt_base_address\t: \tdd gdt\n\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/idt.asm",
    "content": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcli\n\tpush 3\n\tjmp isr_basic\n\t\nisr_4:\n\tcli\n\tpush 4\n\tjmp isr_basic\n\t\nisr_5:\n\tcli\n\tpush 5\n\tjmp isr_basic\n\t\nisr_6:\n\tcli\n\tpush 6\n\tjmp isr_basic\n\t\nisr_7:\n\tcli\n\tpush 7\n\tjmp isr_basic\n\t\nisr_8:\n\tcli\n\tpush 8\n\tjmp isr_basic\n\t\nisr_9:\n\tcli\n\tpush 9\n\tjmp isr_basic\n\t\nisr_10:\n\tcli\n\tpush 10\n\tjmp isr_basic\n\t\nisr_11:\n\tcli\n\tpush 11\n\tjmp isr_basic\n\t\nisr_12:\n\tcli\n\tpush 12\n\tjmp isr_basic\n\t\nisr_13:\n\tcli\n\tpush 13\n\tjmp isr_basic\n\t\nisr_14:\n\tcli\n\tpush 14\n\tjmp isr_basic\n\t\nisr_15:\n\tcli\n\tpush 15\n\tjmp isr_basic\n\t\nisr_16:\n\tcli\n\tpush 16\n\tjmp isr_basic\n\t\nisr_17:\n\tcli\n\tpush 17\n\tjmp isr_basic\n\t\nisr_18:\n\tcli\n\tpush 18\n\tjmp isr_basic\n\t\nisr_19:\n\tcli\n\tpush 19\n\tjmp isr_basic\n\t\nisr_20:\n\tcli\n\tpush 20\n\tjmp isr_basic\n\t\nisr_21:\n\tcli\n\tpush 21\n\tjmp isr_basic\n\nisr_22:\n\tcli\n\tpush 22\n\tjmp isr_basic\n\t\nisr_23:\n\tcli\n\tpush 23\n\tjmp isr_basic\n\t\nisr_24:\n\tcli\n\tpush 24\n\tjmp isr_basic\n\t\nisr_25:\n\tcli\n\tpush 25\n\tjmp isr_basic\n\t\nisr_26:\n\tcli\n\tpush 26\n\tjmp isr_basic\n\t\nisr_27:\n\tcli\n\tpush 27\n\tjmp isr_basic\n\t\nisr_28:\n\tcli\n\tpush 28\n\tjmp isr_basic\n\t\nisr_29:\n\tcli\n\tpush 29\n\tjmp isr_basic\n\t\nisr_30:\n\tcli\n\tpush 30\n\tjmp isr_basic\n\t\nisr_31:\n\tcli\n\tpush 31\n\tjmp isr_basic\n\t\nisr_32:\n    ; Part 1\n    \n    cli ; Step 1\n    \n    pusha ; Step 2\n    \n    ; Step 3\n    mov eax, [esp + 32]\n    push eax  \n    \n    call scheduler ; Step 4\n    \n    ; ... ;\n    \n    ; Part 2\n    \n    ; Step 5\n    mov al, 0x20\n    out 0x20, al\n    \n    ; Step 6\n    add esp, 40d\n    push run_next_process\n    \n    iret ; Step 7\n\t\nisr_33:\n\tcli\n\tpush 33\n\tjmp irq_basic\n\t\nisr_34:\n\tcli\n\tpush 34\n\tjmp irq_basic\n\t\nisr_35:\n\tcli\n\tpush 35\n\tjmp irq_basic\n\t\nisr_36:\n\tcli\n\tpush 36\n\tjmp irq_basic\n\t\nisr_37:\n\tcli\n\tpush 37\n\tjmp irq_basic\n\nisr_38:\n\tcli\n\tpush 38\n\tjmp irq_basic\n\nisr_39:\n\tcli\n\tpush 39\n\tjmp irq_basic\n\nisr_40:\n\tcli\n\tpush 40\n\tjmp irq_basic\n\nisr_41:\n\tcli\n\tpush 41\n\tjmp irq_basic\n\nisr_42:\n\tcli\n\tpush 42\n\tjmp irq_basic\n\nisr_43:\n\tcli\n\tpush 43\n\tjmp irq_basic\n\nisr_44:\n\tcli\n\tpush 44\n\tjmp irq_basic\n\nisr_45:\n\tcli\n\tpush 45\n\tjmp irq_basic\n\nisr_46:\n\tcli\n\tpush 46\n\tjmp irq_basic\n\nisr_47:\n\tcli\n\tpush 47\n\tjmp irq_basic\n\t\nisr_48:\n\tcli\n\tpush 48\n\tjmp irq_basic\n\t\nisr_basic:\n\tcall interrupt_handler\n\t\n\tpop eax\n    \n    sti\n\tiret\n\t\nirq_basic:\n\tcall interrupt_handler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tcmp byte [esp], 40d\n\tjnge irq_basic_end\n\t\n\tmov al, 0xa0\n\tout 0x20, al\n\t\n\tirq_basic_end:\n\t\tpop eax\n        \n        sti\n\t\tiret\n\t\t\nidt:\n\tdw isr_0, 8, 0x8e00, 0x0000\n\tdw isr_1, 8, 0x8e00, 0x0000\n\tdw isr_2, 8, 0x8e00, 0x0000\n\tdw isr_3, 8, 0x8e00, 0x0000\n\tdw isr_4, 8, 0x8e00, 0x0000\n\tdw isr_5, 8, 0x8e00, 0x0000\n\tdw isr_6, 8, 0x8e00, 0x0000\n\tdw isr_7, 8, 0x8e00, 0x0000\n\tdw isr_8, 8, 0x8e00, 0x0000\n\tdw isr_9, 8, 0x8e00, 0x0000\n\tdw isr_10, 8, 0x8e00, 0x0000\n\tdw isr_11, 8, 0x8e00, 0x0000\n\tdw isr_12, 8, 0x8e00, 0x0000\n\tdw isr_13, 8, 0x8e00, 0x0000\n\tdw isr_14, 8, 0x8e00, 0x0000\n\tdw isr_15, 8, 0x8e00, 0x0000\n\tdw isr_16, 8, 0x8e00, 0x0000\n\tdw isr_17, 8, 0x8e00, 0x0000\n\tdw isr_18, 8, 0x8e00, 0x0000\n\tdw isr_19, 8, 0x8e00, 0x0000\n\tdw isr_20, 8, 0x8e00, 0x0000\n\tdw isr_21, 8, 0x8e00, 0x0000\n\tdw isr_22, 8, 0x8e00, 0x0000\n\tdw isr_23, 8, 0x8e00, 0x0000\n\tdw isr_24, 8, 0x8e00, 0x0000\n\tdw isr_25, 8, 0x8e00, 0x0000\n\tdw isr_26, 8, 0x8e00, 0x0000\n\tdw isr_27, 8, 0x8e00, 0x0000\n\tdw isr_28, 8, 0x8e00, 0x0000\n\tdw isr_29, 8, 0x8e00, 0x0000\n\tdw isr_30, 8, 0x8e00, 0x0000\n\tdw isr_31, 8, 0x8e00, 0x0000\n\tdw isr_32, 8, 0x8e00, 0x0000\n\tdw isr_33, 8, 0x8e00, 0x0000\n\tdw isr_34, 8, 0x8e00, 0x0000\n\tdw isr_35, 8, 0x8e00, 0x0000\n\tdw isr_36, 8, 0x8e00, 0x0000\n\tdw isr_37, 8, 0x8e00, 0x0000\n\tdw isr_38, 8, 0x8e00, 0x0000\n\tdw isr_39, 8, 0x8e00, 0x0000\n\tdw isr_40, 8, 0x8e00, 0x0000\n\tdw isr_41, 8, 0x8e00, 0x0000\n\tdw isr_42, 8, 0x8e00, 0x0000\n\tdw isr_43, 8, 0x8e00, 0x0000\n\tdw isr_44, 8, 0x8e00, 0x0000\n\tdw isr_45, 8, 0x8e00, 0x0000\n\tdw isr_46, 8, 0x8e00, 0x0000\n\tdw isr_47, 8, 0x8e00, 0x0000\n\tdw isr_48, 8, 0x8e00, 0x0000\n\t\nidtr:\n\tidt_size_in_bytes\t: \tdw idtr - idt\n\tidt_base_address\t: \tdd idt\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/linker.ld",
    "content": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {\n    code = .; _code = .; __code = .;\n    *(.text)\n  }\n\n  .data :\n  {\n     data = .; _data = .; __data = .;\n     *(.data)\n     *(.rodata)\n  }\n\n  .bss :\n  {\n    bss = .; _bss = .; __bss = .;\n    *(.bss)\n  }\n\n  end = .; _end = .; __end = .;\n} \n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/main.c",
    "content": "#include \"screen.h\"\n#include \"scheduler.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid processD();\n\nvoid kernel_main()\n{\n\tprocess_t p1, p2, p3, p4;\n\t\n\tscreen_init();\n\tprocess_init();\n\tscheduler_init();\n\t\n\tprint( \"Welcome to 539kernel!\" );\n\tprintln();\n\tprint( \"We are now in Protected-mode\" );\n\tprintln();\n\tprinti( 539 );\n\tprintln();\n\t\n    process_create( &processA, &p1 );\n    process_create( &processB, &p2 );\n    process_create( &processC, &p3 );\n    process_create( &processD, &p4 );\n\t\n\twhile( 1 );\n}\n\nvoid interrupt_handler( int interrupt_number )\n{\n\tprintln();\n\tprint( \"Interrupt Received \" );\n\tprinti( interrupt_number );\n}\n\nvoid processA()\n{\n    print( \"Process A,\" );\n\n    while ( 1 )\n        asm( \"mov $5390, %eax\" );\n}\n\nvoid processB()\n{\n    print( \"Process B,\" );\n\n    while ( 1 )\n        asm( \"mov $5391, %eax\" );\n}\n\nvoid processC()\n{\n    print( \"Process C,\" );\n\n    while ( 1 )\n        asm( \"mov $5392, %eax\" );\n}\n\nvoid processD()\n{\n    print( \"Process D,\" );\n\n    while ( 1 )\n        asm( \"mov $5393, %eax\" );\n}\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/process.c",
    "content": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nvoid process_create( int *base_address, process_t *process )\n{   \n    process->pid = curr_pid++;\n    \n    process->context.eax = 0;\n    process->context.ecx = 0;\n    process->context.edx = 0;\n    process->context.ebx = 0;\n    process->context.esp = 0;\n    process->context.ebp = 0;\n    process->context.esi = 0;\n    process->context.edi = 0;\n    process->context.eip = base_address;\n    \n    process->state = READY;\n    process->base_address = base_address;\n    \n    processes[ process->pid ] = process;\n    \n    processes_count++;\n}\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/process.h",
    "content": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;\n} process_context_t;\n\ntypedef struct process\n{\n    int pid;\n    process_context_t context;\n    process_state_t state;\n    int *base_address;\n} process_t;\n\nprocess_t *processes[ 15 ];\n\nint processes_count, curr_pid;\n\nvoid process_init();\nvoid process_create( int *, process_t * );\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/scheduler.c",
    "content": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_process()\n{\n    process_t *next_process = processes[ next_sch_pid ];\n    \n    curr_sch_pid = next_sch_pid;\n    next_sch_pid++;\n    next_sch_pid = next_sch_pid % processes_count;\n    \n    return next_process;\n}\n\nvoid scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )\n{\n    process_t *curr_process;\n    \n    print( \" EAX = \" ); // For Testing Purpose\n    printi( eax ); // For Testing Purpose\n    \n    // ... //\n    \n    // PART 1\n    \n    curr_process = processes[ curr_sch_pid ];\n    next_process = get_next_process();\n    \n    // ... //\n    \n    // PART 2\n\n    if ( curr_process->state == RUNNING )\n    {\n        curr_process->context.eax = eax;\n        curr_process->context.ecx = ecx;\n        curr_process->context.edx = edx;\n        curr_process->context.ebx = ebx;\n        curr_process->context.esp = esp;\n        curr_process->context.ebp = ebp;\n        curr_process->context.esi = esi;\n        curr_process->context.edi = edi;\n        curr_process->context.eip = eip;\n    }\n    \n    curr_process->state = READY;\n    \n    // ... //\n    \n    // PART 3\n    \n    asm( \"  mov %0, %%eax;  \\\n            mov %0, %%ecx;  \\\n            mov %0, %%edx;  \\\n            mov %0, %%ebx;  \\\n            mov %0, %%esi;  \\\n            mov %0, %%edi;\" \n            : : \"r\" ( next_process->context.eax ), \"r\" ( next_process->context.ecx ), \"r\" ( next_process->context.edx ), \"r\" ( next_process->context.ebx ),\n                \"r\" ( next_process->context.esi ), \"r\" ( next_process->context.edi ) );\n    \n    next_process->state = RUNNING;\n}\n\nvoid run_next_process()\n{\n    asm( \"  sti;            \\\n            jmp *%0\" : : \"r\" ( next_process->context.eip ) );\n}\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/scheduler.h",
    "content": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_next_process();\nvoid scheduler( int, int, int, int, int, int, int, int, int );\nvoid run_next_process();\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/screen.c",
    "content": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( char *str )\n{\n\tint currCharLocationInVidMem, currColorLocationInVidMem;\n\t\n\twhile ( *str != '\\0' )\n\t{\n        currCharLocationInVidMem = nextTextPos * 2;\n\t\tcurrColorLocationInVidMem = currCharLocationInVidMem + 1;\n\t\t\n\t\tvideo[ currCharLocationInVidMem ] = *str;\n\t\tvideo[ currColorLocationInVidMem ] = 15;\n\t\t\n\t\tnextTextPos++;\n\t\t\n\t\tstr++;\n\t}\n}\n\nvoid println()\n{\n\tnextTextPos = ++currLine * 80;\n}\n\nvoid printi( int number )\n{\n\tchar* digitToStr[] = { \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" };\n\t\n\tif ( number >= 0 && number <= 9 )\n\t{\n\t\tprint( digitToStr[ number ] );\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tint remaining = number % 10;\n\t\tnumber = number / 10;\n\t\t\n\t\tprinti( number );\n\t\tprinti( remaining );\n\t}\n}\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/screen.h",
    "content": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println();\nvoid printi( int );\n"
  },
  {
    "path": "evolution_by_versions/04_539kernel_version_t/starter.asm",
    "content": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\tcall load_gdt\n\tcall init_video_mode\n\tcall enter_protected_mode\n    call setup_interrupts\n    call load_task_register\n\t\n\tcall 08h:start_kernel\n\t\nload_gdt:\n\tcli\n\tlgdt [gdtr - start]\n\t\n\tret\n\t\nenter_protected_mode:\n\tmov eax, cr0\n\tor eax, 1\n\tmov cr0, eax\n\t\n\tret\n\t\ninit_video_mode:\n\tmov ah, 0h\n\tmov al, 03h\n\tint 10h\n\t\n\tmov ah, 01h\n\tmov cx, 2000h\n\tint 10h\n\t\n\tret\n\t\nsetup_interrupts:\n\tcall remap_pic\n\tcall load_idt\n\t\n\tret\n\t\nremap_pic:\n\tmov al, 11h\n\t\n\tsend_init_cmd_to_pic_master: \t\n\t\tout 0x20, al\n\t\t\n\tsend_init_cmd_to_pic_slave: \t\n\t\tout 0xa0, al\n\t\t\n\t; ... ;\n\t\n\tmake_irq_starts_from_intr_32_in_pic_master:\t\t\n\t\tmov al, 32d\n\t\tout 0x21, al\n\t\n\tmake_irq_starts_from_intr_40_in_pic_slave:\n\t\tmov al, 40d\n\t\tout 0xa1, al \n\t\n\t; ... ;\n\t\n\ttell_pic_master_where_pic_slave_is_connected:\n\t\tmov al, 04h\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_where_pic_master_is_connected:\n\t\tmov al, 02h\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 01h\n\t\n\ttell_pic_master_the_arch_is_x86:\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_the_arch_is_x86:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 0h\n\t\n\tmake_pic_master_enables_all_irqs:\n\t\tout 0x21, al\n\t\n\tmake_pic_slave_enables_all_irqs:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tret\n\t\nload_idt:\n\tlidt [idtr - start]\n\tret\n\t\nload_task_register:\n    mov ax, 40d\n    ltr ax\n    \n    ret\n\t\nbits 32\nstart_kernel:\n\tmov eax, 10h\n\tmov ds, eax\n\tmov ss, eax\n    \n\tmov eax, 0h\n\tmov es, eax\n\tmov fs, eax\n\tmov gs, eax\n\t\n\tsti\n\t\n\tcall kernel_main\n\t\n%include \"gdt.asm\"\n%include \"idt.asm\"\n\ntss:\n    dd 0\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/Makefile",
    "content": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie\nKERNEL_OBJECT = -o kernel.elf\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\t$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf\n\t$(CC) $(KERNEL_FLAGS) process.c -o process.elf\n\t$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf\n\t$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf\n\t$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=8\n\tdd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046\n\tqemu-system-x86_64 -s kernel.img\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/bootstrap.asm",
    "content": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\tcall load_kernel_from_disk\n\tjmp 0900h:0000\n\t\nload_kernel_from_disk:\n\tmov ax, [curr_sector_to_load]\n\tsub ax, 2\n\tmov bx, 512d\n\tmul bx\n\tmov bx, ax\n\t\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h\n\tmov al, 1h\n\tmov ch, 0h\n\tmov cl, [curr_sector_to_load]\n\tmov dh, 0h\n\tmov dl, 80h\n\tint 13h\n\t\t\n\tjc kernel_load_error\n\t\n\tsub byte [number_of_sectors_to_load], 1\n\tadd byte [curr_sector_to_load], 1\n\tcmp byte [number_of_sectors_to_load], 0\n\t\n\tjne load_kernel_from_disk\n\t\n\tret\n    \nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\tjmp $\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\t\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; Reading current cursor position\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n    ; Move the cursor to the beginning\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n\n\tret\n\ntitle_string        db  'The Bootloader of 539kernel.', 0\nmessage_string      db  'The kernel is loading...', 0\nload_error_string   db  'The kernel cannot be loaded', 0\nnumber_of_sectors_to_load \tdb \t10d\ncurr_sector_to_load \t\tdb \t2d\n\ntimes 510-($-$$) db 0\n\ndw 0xAA55\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/gdt.asm",
    "content": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9200, 0x00cf\n\tuserspace_code_descriptor\t: \tdw 0xffff, 0x0000, 0xfa00, 0x00cf\n\tuserspace_data_descriptor\t: \tdw 0xffff, 0x0000, 0xf200, 0x00cf\n\ttss_descriptor\t\t\t\t: \tdw tss + 3, tss, 0x8900, 0x0000\n\ngdtr:\n\tgdt_size_in_bytes\t: \tdw ( 6 * 8 )\n\tgdt_base_address\t: \tdd gdt\n\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/heap.c",
    "content": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\tunsigned int new_object_address = heap_base;\n\t\n\theap_base += bytes;\n\t\n\treturn new_object_address;\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/heap.h",
    "content": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/idt.asm",
    "content": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcli\n\tpush 3\n\tjmp isr_basic\n\t\nisr_4:\n\tcli\n\tpush 4\n\tjmp isr_basic\n\t\nisr_5:\n\tcli\n\tpush 5\n\tjmp isr_basic\n\t\nisr_6:\n\tcli\n\tpush 6\n\tjmp isr_basic\n\t\nisr_7:\n\tcli\n\tpush 7\n\tjmp isr_basic\n\t\nisr_8:\n\tcli\n\tpush 8\n\tjmp isr_basic\n\t\nisr_9:\n\tcli\n\tpush 9\n\tjmp isr_basic\n\t\nisr_10:\n\tcli\n\tpush 10\n\tjmp isr_basic\n\t\nisr_11:\n\tcli\n\tpush 11\n\tjmp isr_basic\n\t\nisr_12:\n\tcli\n\tpush 12\n\tjmp isr_basic\n\t\nisr_13:\n\tcli\n\tpush 13\n\tjmp isr_basic\n\t\nisr_14:\n\tcli\n\tpush 14\n\tjmp isr_basic\n\t\nisr_15:\n\tcli\n\tpush 15\n\tjmp isr_basic\n\t\nisr_16:\n\tcli\n\tpush 16\n\tjmp isr_basic\n\t\nisr_17:\n\tcli\n\tpush 17\n\tjmp isr_basic\n\t\nisr_18:\n\tcli\n\tpush 18\n\tjmp isr_basic\n\t\nisr_19:\n\tcli\n\tpush 19\n\tjmp isr_basic\n\t\nisr_20:\n\tcli\n\tpush 20\n\tjmp isr_basic\n\t\nisr_21:\n\tcli\n\tpush 21\n\tjmp isr_basic\n\nisr_22:\n\tcli\n\tpush 22\n\tjmp isr_basic\n\t\nisr_23:\n\tcli\n\tpush 23\n\tjmp isr_basic\n\t\nisr_24:\n\tcli\n\tpush 24\n\tjmp isr_basic\n\t\nisr_25:\n\tcli\n\tpush 25\n\tjmp isr_basic\n\t\nisr_26:\n\tcli\n\tpush 26\n\tjmp isr_basic\n\t\nisr_27:\n\tcli\n\tpush 27\n\tjmp isr_basic\n\t\nisr_28:\n\tcli\n\tpush 28\n\tjmp isr_basic\n\t\nisr_29:\n\tcli\n\tpush 29\n\tjmp isr_basic\n\t\nisr_30:\n\tcli\n\tpush 30\n\tjmp isr_basic\n\t\nisr_31:\n\tcli\n\tpush 31\n\tjmp isr_basic\n\t\nisr_32:\n    ; Part 1\n    \n    cli ; Step 1\n    \n    pusha ; Step 2\n    \n    ; Step 3\n    mov eax, [esp + 32]\n    push eax  \n    \n    call scheduler ; Step 4\n    \n    ; ... ;\n    \n    ; Part 2\n    \n    ; Step 5\n    mov al, 0x20\n    out 0x20, al\n    \n    ; Step 6\n    add esp, 40d\n    push run_next_process\n    \n    iret ; Step 7\n\t\nisr_33:\n\tcli\n\tpush 33\n\tjmp irq_basic\n\t\nisr_34:\n\tcli\n\tpush 34\n\tjmp irq_basic\n\t\nisr_35:\n\tcli\n\tpush 35\n\tjmp irq_basic\n\t\nisr_36:\n\tcli\n\tpush 36\n\tjmp irq_basic\n\t\nisr_37:\n\tcli\n\tpush 37\n\tjmp irq_basic\n\nisr_38:\n\tcli\n\tpush 38\n\tjmp irq_basic\n\nisr_39:\n\tcli\n\tpush 39\n\tjmp irq_basic\n\nisr_40:\n\tcli\n\tpush 40\n\tjmp irq_basic\n\nisr_41:\n\tcli\n\tpush 41\n\tjmp irq_basic\n\nisr_42:\n\tcli\n\tpush 42\n\tjmp irq_basic\n\nisr_43:\n\tcli\n\tpush 43\n\tjmp irq_basic\n\nisr_44:\n\tcli\n\tpush 44\n\tjmp irq_basic\n\nisr_45:\n\tcli\n\tpush 45\n\tjmp irq_basic\n\nisr_46:\n\tcli\n\tpush 46\n\tjmp irq_basic\n\nisr_47:\n\tcli\n\tpush 47\n\tjmp irq_basic\n\t\nisr_48:\n\tcli\n\tpush 48\n\tjmp irq_basic\n\t\nisr_basic:\n\tcall interrupt_handler\n\t\n\tpop eax\n    \n    sti\n\tiret\n\t\nirq_basic:\n\tcall interrupt_handler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tcmp byte [esp], 40d\n\tjnge irq_basic_end\n\t\n\tmov al, 0xa0\n\tout 0x20, al\n\t\n\tirq_basic_end:\n\t\tpop eax\n        \n        sti\n\t\tiret\n\t\t\nidt:\n\tdw isr_0, 8, 0x8e00, 0x0000\n\tdw isr_1, 8, 0x8e00, 0x0000\n\tdw isr_2, 8, 0x8e00, 0x0000\n\tdw isr_3, 8, 0x8e00, 0x0000\n\tdw isr_4, 8, 0x8e00, 0x0000\n\tdw isr_5, 8, 0x8e00, 0x0000\n\tdw isr_6, 8, 0x8e00, 0x0000\n\tdw isr_7, 8, 0x8e00, 0x0000\n\tdw isr_8, 8, 0x8e00, 0x0000\n\tdw isr_9, 8, 0x8e00, 0x0000\n\tdw isr_10, 8, 0x8e00, 0x0000\n\tdw isr_11, 8, 0x8e00, 0x0000\n\tdw isr_12, 8, 0x8e00, 0x0000\n\tdw isr_13, 8, 0x8e00, 0x0000\n\tdw isr_14, 8, 0x8e00, 0x0000\n\tdw isr_15, 8, 0x8e00, 0x0000\n\tdw isr_16, 8, 0x8e00, 0x0000\n\tdw isr_17, 8, 0x8e00, 0x0000\n\tdw isr_18, 8, 0x8e00, 0x0000\n\tdw isr_19, 8, 0x8e00, 0x0000\n\tdw isr_20, 8, 0x8e00, 0x0000\n\tdw isr_21, 8, 0x8e00, 0x0000\n\tdw isr_22, 8, 0x8e00, 0x0000\n\tdw isr_23, 8, 0x8e00, 0x0000\n\tdw isr_24, 8, 0x8e00, 0x0000\n\tdw isr_25, 8, 0x8e00, 0x0000\n\tdw isr_26, 8, 0x8e00, 0x0000\n\tdw isr_27, 8, 0x8e00, 0x0000\n\tdw isr_28, 8, 0x8e00, 0x0000\n\tdw isr_29, 8, 0x8e00, 0x0000\n\tdw isr_30, 8, 0x8e00, 0x0000\n\tdw isr_31, 8, 0x8e00, 0x0000\n\tdw isr_32, 8, 0x8e00, 0x0000\n\tdw isr_33, 8, 0x8e00, 0x0000\n\tdw isr_34, 8, 0x8e00, 0x0000\n\tdw isr_35, 8, 0x8e00, 0x0000\n\tdw isr_36, 8, 0x8e00, 0x0000\n\tdw isr_37, 8, 0x8e00, 0x0000\n\tdw isr_38, 8, 0x8e00, 0x0000\n\tdw isr_39, 8, 0x8e00, 0x0000\n\tdw isr_40, 8, 0x8e00, 0x0000\n\tdw isr_41, 8, 0x8e00, 0x0000\n\tdw isr_42, 8, 0x8e00, 0x0000\n\tdw isr_43, 8, 0x8e00, 0x0000\n\tdw isr_44, 8, 0x8e00, 0x0000\n\tdw isr_45, 8, 0x8e00, 0x0000\n\tdw isr_46, 8, 0x8e00, 0x0000\n\tdw isr_47, 8, 0x8e00, 0x0000\n\tdw isr_48, 8, 0x8e00, 0x0000\n\t\nidtr:\n\tidt_size_in_bytes\t: \tdw idtr - idt\n\tidt_base_address\t: \tdd idt\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/linker.ld",
    "content": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {\n    code = .; _code = .; __code = .;\n    *(.text)\n  }\n\n  .data :\n  {\n     data = .; _data = .; __data = .;\n     *(.data)\n     *(.rodata)\n  }\n\n  .bss :\n  {\n    bss = .; _bss = .; __bss = .;\n    *(.bss)\n  }\n\n  end = .; _end = .; __end = .;\n} \n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/main.c",
    "content": "#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"heap.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid processD();\n\nvoid kernel_main()\n{\n\theap_init();\n\tpaging_init();\n\tscreen_init();\n\tprocess_init();\n\tscheduler_init();\t\n\t\n\tprint( \"Welcome to 539kernel!\" );\n\tprintln();\n\tprint( \"We are now in Protected-mode\" );\n\tprintln();\n\tprinti( 539 );\n\tprintln();\n\t\n    process_create( &processA );\n\tprocess_create( &processB );\n\tprocess_create( &processC );\n\tprocess_create( &processD );\n\t\n\twhile( 1 );\n}\n\nvoid interrupt_handler( int interrupt_number )\n{\n\tprintln();\n\tprint( \"Interrupt Received \" );\n\tprinti( interrupt_number );\n}\n\nvoid processA()\n{\n    print( \"Process A,\" );\n\n    while ( 1 )\n        asm( \"mov $5390, %eax\" );\n}\n\nvoid processB()\n{\n    print( \"Process B,\" );\n\n    while ( 1 )\n        asm( \"mov $5391, %eax\" );\n}\n\nvoid processC()\n{\n    print( \"Process C,\" );\n\n    while ( 1 )\n        asm( \"mov $5392, %eax\" );\n}\n\nvoid processD()\n{\n    print( \"Process D,\" );\n\n    while ( 1 )\n        asm( \"mov $5393, %eax\" );\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/paging.c",
    "content": "#include \"paging.h\"\n\nint create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )\n{\n\tint entry = 0;\n\t\n\tentry |= present;\n\tentry |= writable << 1;\n\tentry |= privilege_level << 2;\n\tentry |= write_through_cache << 3;\n\tentry |= cache_enabled << 4;\n\tentry |= accessed << 5;\n\tentry |= dirty << 6;\n\tentry |= page_size << 7;\n\t\n\treturn base_address | entry;\n}\n\nvoid paging_init()\n{\n    // PART 1:\n    \n\tunsigned int curr_page_frame = 0;\n\t\n\tpage_directory = kalloc( 4 * 1024 );\n\t\t\n\tfor ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )\n\t{\n\t\tunsigned int *pagetable = kalloc( 4 * PTE_NUM );\n\t\t\n\t\tfor ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )\n\t\t\tpagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t\t\n\t\tpage_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t}\n    \n    // ... //\n    \n    // PART 2\n    \n\tload_page_directory();\n\tenable_paging();\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/paging.h",
    "content": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *page_directory;\n\nvoid paging_init();\nint create_page_entry( int, char, char, char, char, char, char, char, char );\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/process.c",
    "content": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nprocess_t *process_create( int *base_address )\n{\n\tprocess_t *process = kalloc( sizeof( process_t ) );\n\t\n    process->pid = curr_pid++;\n    \n    process->context.eax = 0;\n    process->context.ecx = 0;\n    process->context.edx = 0;\n    process->context.ebx = 0;\n    process->context.esp = 0;\n    process->context.ebp = 0;\n    process->context.esi = 0;\n    process->context.edi = 0;\n    process->context.eip = base_address;\n    \n    process->state = READY;\n    process->base_address = base_address;\n    \n    processes[ process->pid ] = process;\n    \n    processes_count++;\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/process.h",
    "content": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;\n} process_context_t;\n\ntypedef struct process\n{\n    int pid;\n    process_context_t context;\n    process_state_t state;\n    int *base_address;\n} process_t;\n\nprocess_t *processes[ 15 ];\n\nint processes_count, curr_pid;\n\nvoid process_init();\nprocess_t *process_create( int * );\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/scheduler.c",
    "content": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_process()\n{\n    process_t *next_process = processes[ next_sch_pid ];\n    \n    curr_sch_pid = next_sch_pid;\n    next_sch_pid++;\n    next_sch_pid = next_sch_pid % processes_count;\n    \n    return next_process;\n}\n\nvoid scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )\n{\n    process_t *curr_process;\n    \n    print( \" EAX = \" ); // For Testing Purpose\n    printi( eax ); // For Testing Purpose\n    \n    // ... //\n    \n    // PART 1\n    \n    curr_process = processes[ curr_sch_pid ];\n    next_process = get_next_process();\n    \n    // ... //\n    \n    // PART 2\n\n    if ( curr_process->state == RUNNING )\n    {\n        curr_process->context.eax = eax;\n        curr_process->context.ecx = ecx;\n        curr_process->context.edx = edx;\n        curr_process->context.ebx = ebx;\n        curr_process->context.esp = esp;\n        curr_process->context.ebp = ebp;\n        curr_process->context.esi = esi;\n        curr_process->context.edi = edi;\n        curr_process->context.eip = eip;\n    }\n    \n    curr_process->state = READY;\n    \n    // ... //\n    \n    // PART 3\n    \n    asm( \"  mov %0, %%eax;  \\\n            mov %0, %%ecx;  \\\n            mov %0, %%edx;  \\\n            mov %0, %%ebx;  \\\n            mov %0, %%esi;  \\\n            mov %0, %%edi;\" \n            : : \"r\" ( next_process->context.eax ), \"r\" ( next_process->context.ecx ), \"r\" ( next_process->context.edx ), \"r\" ( next_process->context.ebx ),\n                \"r\" ( next_process->context.esi ), \"r\" ( next_process->context.edi ) );\n    \n    next_process->state = RUNNING;\n}\n\nvoid run_next_process()\n{\n    asm( \"  sti;            \\\n            jmp *%0\" : : \"r\" ( next_process->context.eip ) );\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/scheduler.h",
    "content": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_next_process();\nvoid scheduler( int, int, int, int, int, int, int, int, int );\nvoid run_next_process();\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/screen.c",
    "content": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( char *str )\n{\n\tint currCharLocationInVidMem, currColorLocationInVidMem;\n\t\n\twhile ( *str != '\\0' )\n\t{\n        currCharLocationInVidMem = nextTextPos * 2;\n\t\tcurrColorLocationInVidMem = currCharLocationInVidMem + 1;\n\t\t\n\t\tvideo[ currCharLocationInVidMem ] = *str;\n\t\tvideo[ currColorLocationInVidMem ] = 15;\n\t\t\n\t\tnextTextPos++;\n\t\t\n\t\tstr++;\n\t}\n}\n\nvoid println()\n{\n\tnextTextPos = ++currLine * 80;\n}\n\nvoid printi( int number )\n{\n\tchar* digitToStr[] = { \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" };\n\t\n\tif ( number >= 0 && number <= 9 )\n\t{\n\t\tprint( digitToStr[ number ] );\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tint remaining = number % 10;\n\t\tnumber = number / 10;\n\t\t\n\t\tprinti( number );\n\t\tprinti( remaining );\n\t}\n}\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/screen.h",
    "content": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println();\nvoid printi( int );\n"
  },
  {
    "path": "evolution_by_versions/05_539kernel_version_g/starter.asm",
    "content": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglobal load_page_directory\nglobal enable_paging\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\tcall load_gdt\n\tcall init_video_mode\n\tcall enter_protected_mode\n    call setup_interrupts\n    call load_task_register\n\t\n\tcall 08h:start_kernel\n\t\nload_gdt:\n\tcli\n\tlgdt [gdtr - start]\n\t\n\tret\n\t\nenter_protected_mode:\n\tmov eax, cr0\n\tor eax, 1\n\tmov cr0, eax\n\t\n\tret\n\t\ninit_video_mode:\n\tmov ah, 0h\n\tmov al, 03h\n\tint 10h\n\t\n\tmov ah, 01h\n\tmov cx, 2000h\n\tint 10h\n\t\n\tret\n\t\nsetup_interrupts:\n\tcall remap_pic\n\tcall load_idt\n\t\n\tret\n\t\nremap_pic:\n\tmov al, 11h\n\t\n\tsend_init_cmd_to_pic_master: \t\n\t\tout 0x20, al\n\t\t\n\tsend_init_cmd_to_pic_slave: \t\n\t\tout 0xa0, al\n\t\t\n\t; ... ;\n\t\n\tmake_irq_starts_from_intr_32_in_pic_master:\t\t\n\t\tmov al, 32d\n\t\tout 0x21, al\n\t\n\tmake_irq_starts_from_intr_40_in_pic_slave:\n\t\tmov al, 40d\n\t\tout 0xa1, al \n\t\n\t; ... ;\n\t\n\ttell_pic_master_where_pic_slave_is_connected:\n\t\tmov al, 04h\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_where_pic_master_is_connected:\n\t\tmov al, 02h\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 01h\n\t\n\ttell_pic_master_the_arch_is_x86:\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_the_arch_is_x86:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 0h\n\t\n\tmake_pic_master_enables_all_irqs:\n\t\tout 0x21, al\n\t\n\tmake_pic_slave_enables_all_irqs:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tret\n\t\nload_idt:\n\tlidt [idtr - start]\n\tret\n\t\nload_task_register:\n    mov ax, 40d\n    ltr ax\n    \n    ret\n\t\nbits 32\nload_page_directory:\n\tmov eax, [page_directory]\n\tmov cr3, eax\n\t\n\tret\n\t\nenable_paging:\n\tmov eax, cr0\n\tor eax, 80000000h\n\tmov cr0, eax\n\t\n\tret\n\t\nstart_kernel:\n\tmov eax, 10h\n\tmov ds, eax\n\tmov ss, eax\n    \n\tmov eax, 0h\n\tmov es, eax\n\tmov fs, eax\n\tmov gs, eax\n\t\n\tsti\n\t\n\tcall kernel_main\n\t\n%include \"gdt.asm\"\n%include \"idt.asm\"\n\ntss:\n    dd 0\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/Makefile",
    "content": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\nKERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie\nKERNEL_OBJECT = -o kernel.elf\n\nbuild: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\t$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf\n\t$(CC) $(KERNEL_FLAGS) process.c -o process.elf\n\t$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf\n\t$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf\n\t$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf\n\t$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf\n\t$(CC) $(KERNEL_FLAGS) str.c -o str.elf\n\t$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20\n\tdd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046\n\tbochs -f bochs\n\t#qemu-system-x86_64 -machine pc kernel.img\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/ata.c",
    "content": "#include \"ata.h\"\n\nvoid wait_drive_until_ready()\n{\n\tint status = 0;\n\t\n\tdo\n\t{\n\t\tstatus = dev_read( BASE_PORT + 7 );\n\t} while ( ( status ^ 0x80 ) == 128 );\n}\n\nvoid *read_disk_chs( int sector )\n{\n\t// Part 1\n\t\n\tdev_write( BASE_PORT + 6, 0x0a0 );\n\tdev_write( BASE_PORT + 2, 1 );\n\tdev_write( BASE_PORT + 3, sector );\n\tdev_write( BASE_PORT + 4, 0 );\n\tdev_write( BASE_PORT + 5, 0 );\n\tdev_write( BASE_PORT + 7, 0x20 );\n\t\n    // ... //\n    \n    // Part 2\n    wait_drive_until_ready();\n\t\n    // ... //\n    \n\t// Part 3\n\t\n    short *buffer = kalloc( SECTOR_SIZE );\n    \n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tbuffer[ currByte ] = dev_read( BASE_PORT );\n\n\treturn buffer;\n}\n\nvoid *read_disk( int address )\n{\n\tdev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) );\n\tdev_write( BASE_PORT + 2, 1 );\n\tdev_write( BASE_PORT + 3, address & 0x000000FF );\n\tdev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 );\n\tdev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 );\n\tdev_write( BASE_PORT + 7, 0x20 );\n\t\n    // ... //\n    \n    wait_drive_until_ready();\n\t\n    // ... //\n    \n    short *buffer = kalloc( SECTOR_SIZE );\n    \n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tbuffer[ currByte ] = dev_read( BASE_PORT );\n\n\treturn buffer;\n}\n\nvoid write_disk_chs( int sector, short *buffer )\n{\n\tdev_write( BASE_PORT + 6, 0x0a0 );\n\tdev_write( BASE_PORT + 2, 1 );\n\tdev_write( BASE_PORT + 3, sector );\n\tdev_write( BASE_PORT + 4, 0 );\n\tdev_write( BASE_PORT + 5, 0 );\n\tdev_write( BASE_PORT + 7, 0x30 );\n\t\n\twait_drive_until_ready();\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tdev_write_word( BASE_PORT, buffer[ currByte ] );\n    \n\twait_drive_until_ready();\n}\n\nvoid write_disk( int address, short *buffer )\n{\n\tdev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) );\n\tdev_write( BASE_PORT + 2, 1 );\n\tdev_write( BASE_PORT + 3, address & 0x000000FF );\n\tdev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 );\n\tdev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 );\n\tdev_write( BASE_PORT + 7, 0x30 );\n\t\n\twait_drive_until_ready();\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tdev_write_word( BASE_PORT, buffer[ currByte ] );\n\t\t\n\twait_drive_until_ready();\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/ata.h",
    "content": "#define BASE_PORT 0x1F0\n#define SECTOR_SIZE 512\n\nvoid wait_drive_until_ready();\n\nvoid *read_disk( int );\nvoid write_disk( int, short * );\n\nvoid *read_disk_chs( int );\nvoid write_disk_chs( int, short * );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/bochs",
    "content": "plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1\nconfig_interface: textconfig\ndisplay_library: x, options=\"gui_debug\"\nmemory: host=32, guest=32\nromimage: file=\"/usr/share/bochs/BIOS-bochs-latest\"\nvgaromimage: file=\"/usr/share/bochs/VGABIOS-lgpl-latest\"\nboot: disk\nata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14\nata0-master: type=disk, mode=flat, translation=auto, path=\"kernel.img\", cylinders=2, heads=16, spt=63, biosdetect=auto, model=\"Generic 1234\"\npci: enabled=1, chipset=i440fx\nvga: extension=vbe, update_freq=5\ncpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0\ncpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, avx=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, tbm=0, fma4=0, vmx=1, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1\ncpuid: vendor_string=\"GenuineIntel\"\ncpuid: brand_string=\"              Intel(R) Pentium(R) 4 CPU        \"\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/bootstrap.asm",
    "content": "start:\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\n\tmov si, title_string\n\tcall print_string\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\tcall load_kernel_from_disk\n\tjmp 0900h:0000\n\t\nload_kernel_from_disk:\n\tmov ax, [curr_sector_to_load]\n\tsub ax, 2\n\tmov bx, 512d\n\tmul bx\n\tmov bx, ax\n\t\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h\n\tmov al, 1h\n\tmov ch, 0h\n\tmov cl, [curr_sector_to_load]\n\tmov dh, 0h\n\tmov dl, 80h\n\tint 13h\n\t\t\n\tjc kernel_load_error\n\t\n\tsub byte [number_of_sectors_to_load], 1\n\tadd byte [curr_sector_to_load], 1\n\tcmp byte [number_of_sectors_to_load], 0\n\t\n\tjne load_kernel_from_disk\n\t\n\tret\n    \nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\tjmp $\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\t\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; Reading current cursor position\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n    ; Move the cursor to the beginning\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n\n\tret\n\ntitle_string        db  'The Bootloader of 539kernel.', 0\nmessage_string      db  'The kernel is loading...', 0\nload_error_string   db  'The kernel cannot be loaded', 0\nnumber_of_sectors_to_load \tdb \t15d\ncurr_sector_to_load \t\tdb \t2d\n\ntimes 510-($-$$) db 0\n\ndw 0xAA55\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/filesystem.c",
    "content": "#include \"filesystem.h\"\n\nvoid filesystem_init()\n{\n\tbase_block = read_disk( BASE_BLOCK_ADDRESS );\n}\n\nvoid create_file( char *filename, char *buffer )\n{\n\tint metadata_lba = ( base_block->head == 0 ) ? BASE_BLOCK_ADDRESS + 1 : base_block->tail + 2;\n\tint file_lba = metadata_lba + 1;\n\t\n\tmetadata_t *metadata = kalloc( sizeof( metadata_t ) );\n\t\n\tmetadata->next_file_address = 0;\n    \n    int currIdx;\n\t\n\tfor ( currIdx = 0; *filename != '\\0' && currIdx < FILENAME_LENGTH - 1; currIdx++, filename++ )\n\t\tmetadata->filename[ currIdx ] = *filename;\n\t\n\tmetadata->filename[ currIdx ] = '\\0';\n\t\n\twrite_disk( metadata_lba, metadata );\n\twrite_disk( file_lba, buffer );\n\t\n\tif ( base_block->head == 0 )\n\t{\n\t\tupdate_base_block( metadata_lba, metadata_lba );\n\t}\n\telse\n\t{\t\n\t\tmetadata_t *tail_metadata = load_metadata( base_block->tail );\n\t\t\n\t\ttail_metadata->next_file_address = metadata_lba;\n\t\t\n\t\twrite_disk( base_block->tail, tail_metadata );\t\t\n\t\tupdate_base_block( base_block->head, metadata_lba );\n\t}\n}\n\n\nchar **list_files()\n{\n    // Part 1\n    \n\tif ( base_block->head == 0 )\n\t\treturn -1;\n\t\n    // Part 2\n    \n\tchar **list;\n\t\n\tlist = kalloc( get_files_number() * sizeof( char * ) );\n\t\n    // Part 3\n    \n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\t\n\tint idx = 0;\n\t\n\twhile ( 1 )\n\t{\n\t\tlist[ idx ] = curr_file->filename;\n\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\n\t\t\n\t\tidx++;\n\t}\n\t\n\treturn list;\n}\n\n\n\nchar *read_file( char *filename )\n{\n\tint address = get_address_by_filename( filename );\n\t\n\tif ( address == 0 )\n\t\treturn 0;\n\n\tchar *buffer = read_disk( address + 1 );\n\t\n\treturn buffer;\n}\n\n\n\nvoid delete_file( char *filename )\n{\t\n    // Part 1\n    \n\tint curr_file_address = get_address_by_filename( filename );\n\t\n\tif ( curr_file_address == 0 )\n\t\treturn;\n\t\n\tmetadata_t *curr_file_metadata = read_disk( curr_file_address );\n\t\n    // Part 2\n    \n    if ( get_files_number() == 1 )\n\t{\n\t\tupdate_base_block( 0, 0 );\n\t\t\n\t\treturn;\n\t}\n    \n    // Part 3\n\tif ( curr_file_address == base_block->head )\n\t{\n\t\tupdate_base_block( curr_file_metadata->next_file_address, base_block->tail );\n\t}\n    // Part 4\n\telse\n\t{\n\t\tint prev_file_address = get_prev_file_address( curr_file_address );\n\t\t\n\t\tmetadata_t *prev_file = load_metadata( prev_file_address );\n\n\t\tprev_file->next_file_address = curr_file_metadata->next_file_address;\n\t\t\n\t\twrite_disk( prev_file_address, prev_file );\n\t\t\n\t\tif ( curr_file_address == base_block->tail )\n\t\t\tupdate_base_block( base_block->head, prev_file_address );\n\t}\n}\n\n// ... //\n\nvoid update_base_block( int new_head, int new_tail )\n{\n\tbase_block->head = new_head;\n\tbase_block->tail = new_tail;\n\t\n\twrite_disk( BASE_BLOCK_ADDRESS, base_block );\n}\n\nmetadata_t *load_metadata( int address )\n{\n\tmetadata_t *metadata = read_disk( address );\n\t\n\treturn metadata;\n}\n\nint get_address_by_filename( char *filename )\n{\n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\tint curr_file_address = base_block->head;\n\t\n\tint idx = 0;\n\t\n\twhile ( 1 )\n\t{\n\t\tif ( strcmp( curr_file->filename, filename ) == 1 )\n\t\t\treturn curr_file_address;\n\t\t\t\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file_address = curr_file->next_file_address;\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\t\t\n\t}\n\t\n\treturn 0;\n}\n\nint get_prev_file_address( int address )\n{\n\tmetadata_t *prev_file = load_metadata( base_block->head );\n\tint prev_file_address = base_block->head;\n\n\twhile ( 1 )\n\t{\n\t\tif ( prev_file->next_file_address == address )\n\t\t\treturn prev_file_address;\n\t\t\n\t\tprev_file_address = prev_file->next_file_address;\n\t\tprev_file = load_metadata( prev_file->next_file_address );\n\t}\n\t\t\n\treturn -1;\n}\n\nint get_files_number()\n{\n\tif ( base_block->head == 0 )\n\t\treturn 0;\n\t\n\tint files_number = 0;\n\t\n\t// ... //\n\t\n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\t\n\twhile ( 1 )\n\t{\n\t\tfiles_number++;\n\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\n\t}\n\t\n\treturn files_number;\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/filesystem.h",
    "content": "#define BASE_BLOCK_ADDRESS 100\n#define FILENAME_LENGTH 256\n\ntypedef struct\n{\n\tint head, tail;\n} base_block_t;\n\ntypedef struct\n{\n\tchar filename[ FILENAME_LENGTH ];\n\tint next_file_address;\n} metadata_t;\n\nbase_block_t *base_block;\n\nvoid filesystem_init();\nvoid create_file( char *, char * );\nchar **list_files();\nchar *read_file( char * );\n\n// Auxiliary Functions\nmetadata_t *load_metadata( int );\nint get_address_by_filename( char * );\nint get_prev_file_address( int );\nint get_files_number();\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/gdt.asm",
    "content": "gdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9200, 0x00cf\n\tuserspace_code_descriptor\t: \tdw 0xffff, 0x0000, 0xfa00, 0x00cf\n\tuserspace_data_descriptor\t: \tdw 0xffff, 0x0000, 0xf200, 0x00cf\n\ttss_descriptor\t\t\t\t: \tdw tss + 3, tss, 0x8900, 0x0000\n\ngdtr:\n\tgdt_size_in_bytes\t: \tdw ( 6 * 8 )\n\tgdt_base_address\t: \tdd gdt\n\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/heap.c",
    "content": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\tunsigned int new_object_address = heap_base;\n\t\n\theap_base += bytes;\n\t\n\treturn new_object_address;\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/heap.h",
    "content": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/idt.asm",
    "content": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcli\n\tpush 3\n\tjmp isr_basic\n\t\nisr_4:\n\tcli\n\tpush 4\n\tjmp isr_basic\n\t\nisr_5:\n\tcli\n\tpush 5\n\tjmp isr_basic\n\t\nisr_6:\n\tcli\n\tpush 6\n\tjmp isr_basic\n\t\nisr_7:\n\tcli\n\tpush 7\n\tjmp isr_basic\n\t\nisr_8:\n\tcli\n\tpush 8\n\tjmp isr_basic\n\t\nisr_9:\n\tcli\n\tpush 9\n\tjmp isr_basic\n\t\nisr_10:\n\tcli\n\tpush 10\n\tjmp isr_basic\n\t\nisr_11:\n\tcli\n\tpush 11\n\tjmp isr_basic\n\t\nisr_12:\n\tcli\n\tpush 12\n\tjmp isr_basic\n\t\nisr_13:\n\tcli\n\tpush 13\n\tjmp isr_basic\n\t\nisr_14:\n\tcli\n\tpush 14\n\tjmp isr_basic\n\t\nisr_15:\n\tcli\n\tpush 15\n\tjmp isr_basic\n\t\nisr_16:\n\tcli\n\tpush 16\n\tjmp isr_basic\n\t\nisr_17:\n\tcli\n\tpush 17\n\tjmp isr_basic\n\t\nisr_18:\n\tcli\n\tpush 18\n\tjmp isr_basic\n\t\nisr_19:\n\tcli\n\tpush 19\n\tjmp isr_basic\n\t\nisr_20:\n\tcli\n\tpush 20\n\tjmp isr_basic\n\t\nisr_21:\n\tcli\n\tpush 21\n\tjmp isr_basic\n\nisr_22:\n\tcli\n\tpush 22\n\tjmp isr_basic\n\t\nisr_23:\n\tcli\n\tpush 23\n\tjmp isr_basic\n\t\nisr_24:\n\tcli\n\tpush 24\n\tjmp isr_basic\n\t\nisr_25:\n\tcli\n\tpush 25\n\tjmp isr_basic\n\t\nisr_26:\n\tcli\n\tpush 26\n\tjmp isr_basic\n\t\nisr_27:\n\tcli\n\tpush 27\n\tjmp isr_basic\n\t\nisr_28:\n\tcli\n\tpush 28\n\tjmp isr_basic\n\t\nisr_29:\n\tcli\n\tpush 29\n\tjmp isr_basic\n\t\nisr_30:\n\tcli\n\tpush 30\n\tjmp isr_basic\n\t\nisr_31:\n\tcli\n\tpush 31\n\tjmp isr_basic\n\t\nisr_32:\n    ; Part 1\n    \n    cli ; Step 1\n    \n    pusha ; Step 2\n    \n    ; Step 3\n    mov eax, [esp + 32]\n    push eax  \n    \n    call scheduler ; Step 4\n    \n    ; ... ;\n    \n    ; Part 2\n    \n    ; Step 5\n    mov al, 0x20\n    out 0x20, al\n    \n    ; Step 6\n    add esp, 40d\n    push run_next_process\n    \n    iret ; Step 7\n\t\nisr_33:\n\tcli\n\tpush 33\n\tjmp irq_basic\n\t\nisr_34:\n\tcli\n\tpush 34\n\tjmp irq_basic\n\t\nisr_35:\n\tcli\n\tpush 35\n\tjmp irq_basic\n\t\nisr_36:\n\tcli\n\tpush 36\n\tjmp irq_basic\n\t\nisr_37:\n\tcli\n\tpush 37\n\tjmp irq_basic\n\nisr_38:\n\tcli\n\tpush 38\n\tjmp irq_basic\n\nisr_39:\n\tcli\n\tpush 39\n\tjmp irq_basic\n\nisr_40:\n\tcli\n\tpush 40\n\tjmp irq_basic\n\nisr_41:\n\tcli\n\tpush 41\n\tjmp irq_basic\n\nisr_42:\n\tcli\n\tpush 42\n\tjmp irq_basic\n\nisr_43:\n\tcli\n\tpush 43\n\tjmp irq_basic\n\nisr_44:\n\tcli\n\tpush 44\n\tjmp irq_basic\n\nisr_45:\n\tcli\n\tpush 45\n\tjmp irq_basic\n\nisr_46:\n\tcli\n\tpush 46\n\tjmp irq_basic\n\nisr_47:\n\tcli\n\tpush 47\n\tjmp irq_basic\n\t\nisr_48:\n\tcli\n\tpush 48\n\tjmp irq_basic\n\t\nisr_basic:\n\tcall interrupt_handler\n\t\n\tpop eax\n    \n    sti\n\tiret\n\t\nirq_basic:\n\tcall interrupt_handler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tcmp byte [esp], 40d\n\tjnge irq_basic_end\n\t\n\tmov al, 0xa0\n\tout 0x20, al\n\t\n\tirq_basic_end:\n\t\tpop eax\n        \n        sti\n\t\tiret\n\t\t\nidt:\n\tdw isr_0, 8, 0x8e00, 0x0000\n\tdw isr_1, 8, 0x8e00, 0x0000\n\tdw isr_2, 8, 0x8e00, 0x0000\n\tdw isr_3, 8, 0x8e00, 0x0000\n\tdw isr_4, 8, 0x8e00, 0x0000\n\tdw isr_5, 8, 0x8e00, 0x0000\n\tdw isr_6, 8, 0x8e00, 0x0000\n\tdw isr_7, 8, 0x8e00, 0x0000\n\tdw isr_8, 8, 0x8e00, 0x0000\n\tdw isr_9, 8, 0x8e00, 0x0000\n\tdw isr_10, 8, 0x8e00, 0x0000\n\tdw isr_11, 8, 0x8e00, 0x0000\n\tdw isr_12, 8, 0x8e00, 0x0000\n\tdw isr_13, 8, 0x8e00, 0x0000\n\tdw isr_14, 8, 0x8e00, 0x0000\n\tdw isr_15, 8, 0x8e00, 0x0000\n\tdw isr_16, 8, 0x8e00, 0x0000\n\tdw isr_17, 8, 0x8e00, 0x0000\n\tdw isr_18, 8, 0x8e00, 0x0000\n\tdw isr_19, 8, 0x8e00, 0x0000\n\tdw isr_20, 8, 0x8e00, 0x0000\n\tdw isr_21, 8, 0x8e00, 0x0000\n\tdw isr_22, 8, 0x8e00, 0x0000\n\tdw isr_23, 8, 0x8e00, 0x0000\n\tdw isr_24, 8, 0x8e00, 0x0000\n\tdw isr_25, 8, 0x8e00, 0x0000\n\tdw isr_26, 8, 0x8e00, 0x0000\n\tdw isr_27, 8, 0x8e00, 0x0000\n\tdw isr_28, 8, 0x8e00, 0x0000\n\tdw isr_29, 8, 0x8e00, 0x0000\n\tdw isr_30, 8, 0x8e00, 0x0000\n\tdw isr_31, 8, 0x8e00, 0x0000\n\tdw isr_32, 8, 0x8e00, 0x0000\n\tdw isr_33, 8, 0x8e00, 0x0000\n\tdw isr_34, 8, 0x8e00, 0x0000\n\tdw isr_35, 8, 0x8e00, 0x0000\n\tdw isr_36, 8, 0x8e00, 0x0000\n\tdw isr_37, 8, 0x8e00, 0x0000\n\tdw isr_38, 8, 0x8e00, 0x0000\n\tdw isr_39, 8, 0x8e00, 0x0000\n\tdw isr_40, 8, 0x8e00, 0x0000\n\tdw isr_41, 8, 0x8e00, 0x0000\n\tdw isr_42, 8, 0x8e00, 0x0000\n\tdw isr_43, 8, 0x8e00, 0x0000\n\tdw isr_44, 8, 0x8e00, 0x0000\n\tdw isr_45, 8, 0x8e00, 0x0000\n\tdw isr_46, 8, 0x8e00, 0x0000\n\tdw isr_47, 8, 0x8e00, 0x0000\n\tdw isr_48, 8, 0x8e00, 0x0000\n\t\nidtr:\n\tidt_size_in_bytes\t: \tdw idtr - idt\n\tidt_base_address\t: \tdd idt\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/linker.ld",
    "content": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {\n    code = .; _code = .; __code = .;\n    *(.text)\n  }\n\n  .data :\n  {\n     data = .; _data = .; __data = .;\n     *(.data)\n     *(.rodata)\n  }\n\n  .bss :\n  {\n    bss = .; _bss = .; __bss = .;\n    *(.bss)\n  }\n\n  end = .; _end = .; __end = .;\n} \n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/main.c",
    "content": "#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"heap.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid processD();\n\nvoid print_fs();\n\nvoid kernel_main()\n{\n\theap_init();\n\tpaging_init();\n\tscreen_init();\n\tprocess_init();\n\tscheduler_init();\n\tfilesystem_init();\n\t\n\tprint( \"Welcome to 539kernel!\" );\n\tprintln();\n\tprint( \"We are now in Protected-mode\" );\n\tprintln();\n\tprinti( 539 );\n\tprintln();\n\t\n    process_create( &processA );\n\tprocess_create( &processB );\n\tprocess_create( &processC );\n\tprocess_create( &processD );\n\t\n\t// ... //\n\t\n\tchar *data = kalloc( 512 );\n\tstrcpy( data, \"The content of the first file on 539filesystem\" );\t\n\tcreate_file( \"first_file\", data );\n\t\n\t// ... //\n\t\n\tchar *data2 = kalloc( 512 );\n\tstrcpy( data2, \"SECOND FILE in 539filesystem\" );\n\tcreate_file( \"second_file\", data2 );\n\t\n\t// ... //\n\t\n\tchar *data3 = kalloc( 512 );\n\tstrcpy( data3, \"THIRD FILE in 539filesystem\" );\n\tcreate_file( \"third_file\", data3 );\n\t\t\n\t// ... //\n\t\n\tprint( read_file( \"first_file\" ) ); println();\n\tprint( read_file( \"second_file\" ) ); println();\n\tprint( read_file( \"third_file\" ) ); println();\n\t\n\t// ... //\n\t\n\tprint_fs();\n\tdelete_file( \"first_file\" );\n\tprint_fs();\n\n\t// ... //\n\t\n\twhile( 1 );\n}\n\nvoid print_fs()\n{\n\tchar **files = list_files();\n\n\tfor ( int currIdx = 0; currIdx < get_files_number(); currIdx++ )\n\t{\n\t\tprint( \"File: \" );\n\t\tprint( files[ currIdx ] );\n\t\tprintln();\n\t}\n\t\n\tprint( \"==\" );\n\tprintln();\n}\n\nvoid interrupt_handler( int interrupt_number )\n{\n\t//println();\n\t//print( \"Interrupt Received \" );\n\t//printi( interrupt_number );\n}\n\nvoid processA()\n{\n    print( \"Process A,\" );\n\n    while ( 1 )\n        asm( \"mov $5390, %eax\" );\n}\n\nvoid processB()\n{\n    print( \"Process B,\" );\n\n    while ( 1 )\n        asm( \"mov $5391, %eax\" );\n}\n\nvoid processC()\n{\n    print( \"Process C,\" );\n\n    while ( 1 )\n        asm( \"mov $5392, %eax\" );\n}\n\nvoid processD()\n{\n    print( \"Process D,\" );\n\n    while ( 1 )\n        asm( \"mov $5393, %eax\" );\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/paging.c",
    "content": "#include \"paging.h\"\n\nint create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )\n{\n\tint entry = 0;\n\t\n\tentry |= present;\n\tentry |= writable << 1;\n\tentry |= privilege_level << 2;\n\tentry |= write_through_cache << 3;\n\tentry |= cache_enabled << 4;\n\tentry |= accessed << 5;\n\tentry |= dirty << 6;\n\tentry |= page_size << 7;\n\t\n\treturn base_address | entry;\n}\n\nvoid paging_init()\n{\n    // PART 1:\n    \n\tunsigned int curr_page_frame = 0;\n\t\n\tpage_directory = kalloc( 4 * 1024 );\n\t\t\n\tfor ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )\n\t{\n\t\tunsigned int *pagetable = kalloc( 4 * PTE_NUM );\n\t\t\n\t\tfor ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )\n\t\t\tpagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t\t\n\t\tpage_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t}\n    \n    // ... //\n    \n    // PART 2\n    \n\tload_page_directory();\n\tenable_paging();\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/paging.h",
    "content": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *page_directory;\n\nvoid paging_init();\nint create_page_entry( int, char, char, char, char, char, char, char, char );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/process.c",
    "content": "#include \"process.h\"\n\nvoid process_init()\n{\n    processes_count = 0;\n    curr_pid = 0;\n}\n\nprocess_t *process_create( int *base_address )\n{\n\tprocess_t *process = kalloc( sizeof( process_t ) );\n\t\n    process->pid = curr_pid++;\n    \n    process->context.eax = 0;\n    process->context.ecx = 0;\n    process->context.edx = 0;\n    process->context.ebx = 0;\n    process->context.esp = 0;\n    process->context.ebp = 0;\n    process->context.esi = 0;\n    process->context.edi = 0;\n    process->context.eip = base_address;\n    \n    process->state = READY;\n    process->base_address = base_address;\n    \n    processes[ process->pid ] = process;\n    \n    processes_count++;\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/process.h",
    "content": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n    int eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;\n} process_context_t;\n\ntypedef struct process\n{\n    int pid;\n    process_context_t context;\n    process_state_t state;\n    int *base_address;\n} process_t;\n\nprocess_t *processes[ 15 ];\n\nint processes_count, curr_pid;\n\nvoid process_init();\nprocess_t *process_create( int * );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/scheduler.c",
    "content": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n    next_sch_pid = 0;\n    curr_sch_pid = 0;\n}\n\nprocess_t *get_next_process()\n{\n    process_t *next_process = processes[ next_sch_pid ];\n    \n    curr_sch_pid = next_sch_pid;\n    next_sch_pid++;\n    next_sch_pid = next_sch_pid % processes_count;\n    \n    return next_process;\n}\n\nvoid scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )\n{\n    process_t *curr_process;\n    \n    print( \" EAX = \" ); // For Testing Purpose\n    printi( eax ); // For Testing Purpose\n    \n    // ... //\n    \n    // PART 1\n    \n    curr_process = processes[ curr_sch_pid ];\n    next_process = get_next_process();\n    \n    // ... //\n    \n    // PART 2\n\n    if ( curr_process->state == RUNNING )\n    {\n        curr_process->context.eax = eax;\n        curr_process->context.ecx = ecx;\n        curr_process->context.edx = edx;\n        curr_process->context.ebx = ebx;\n        curr_process->context.esp = esp;\n        curr_process->context.ebp = ebp;\n        curr_process->context.esi = esi;\n        curr_process->context.edi = edi;\n        curr_process->context.eip = eip;\n    }\n    \n    curr_process->state = READY;\n    \n    // ... //\n    \n    // PART 3\n    \n    asm( \"  mov %0, %%eax;  \\\n            mov %0, %%ecx;  \\\n            mov %0, %%edx;  \\\n            mov %0, %%ebx;  \\\n            mov %0, %%esi;  \\\n            mov %0, %%edi;\" \n            : : \"r\" ( next_process->context.eax ), \"r\" ( next_process->context.ecx ), \"r\" ( next_process->context.edx ), \"r\" ( next_process->context.ebx ),\n                \"r\" ( next_process->context.esi ), \"r\" ( next_process->context.edi ) );\n    \n    next_process->state = RUNNING;\n}\n\nvoid run_next_process()\n{\n    asm( \"  sti;            \\\n            jmp *%0\" : : \"r\" ( next_process->context.eip ) );\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/scheduler.h",
    "content": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_next_process();\nvoid scheduler( int, int, int, int, int, int, int, int, int );\nvoid run_next_process();\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/screen.c",
    "content": "#include \"screen.h\"\n\nvoid screen_init()\n{\n    video = 0xB8000;\n    nextTextPos = 0;\n    currLine = 0;\n}\n\nvoid print( char *str )\n{\n\tint currCharLocationInVidMem, currColorLocationInVidMem;\n\t\n\twhile ( *str != '\\0' )\n\t{\n        currCharLocationInVidMem = nextTextPos * 2;\n\t\tcurrColorLocationInVidMem = currCharLocationInVidMem + 1;\n\t\t\n\t\tvideo[ currCharLocationInVidMem ] = *str;\n\t\tvideo[ currColorLocationInVidMem ] = 15;\n\t\t\n\t\tnextTextPos++;\n\t\t\n\t\tstr++;\n\t}\n}\n\nvoid println()\n{\n\tnextTextPos = ++currLine * 80;\n}\n\nvoid printi( int number )\n{\n\tchar* digitToStr[] = { \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" };\n\t\n\tif ( number >= 0 && number <= 9 )\n\t{\n\t\tprint( digitToStr[ number ] );\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tint remaining = number % 10;\n\t\tnumber = number / 10;\n\t\t\n\t\tprinti( number );\n\t\tprinti( remaining );\n\t}\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/screen.h",
    "content": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println();\nvoid printi( int );\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/starter.asm",
    "content": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglobal load_page_directory\nglobal enable_paging\nglobal dev_write\nglobal dev_write_word\nglobal dev_read\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\tcall load_gdt\n\tcall init_video_mode\n\tcall enter_protected_mode\n    call setup_interrupts\n    call load_task_register\n\t\n\tcall 08h:start_kernel\n\t\nload_gdt:\n\tcli\n\tlgdt [gdtr - start]\n\t\n\tret\n\t\nenter_protected_mode:\n\tmov eax, cr0\n\tor eax, 1\n\tmov cr0, eax\n\t\n\tret\n\t\ninit_video_mode:\n\tmov ah, 0h\n\tmov al, 03h\n\tint 10h\n\t\n\tmov ah, 01h\n\tmov cx, 2000h\n\tint 10h\n\t\n\tret\n\t\nsetup_interrupts:\n\tcall remap_pic\n\tcall load_idt\n\t\n\tret\n\t\nremap_pic:\n\tmov al, 11h\n\t\n\tsend_init_cmd_to_pic_master: \t\n\t\tout 0x20, al\n\t\t\n\tsend_init_cmd_to_pic_slave: \t\n\t\tout 0xa0, al\n\t\t\n\t; ... ;\n\t\n\tmake_irq_starts_from_intr_32_in_pic_master:\t\t\n\t\tmov al, 32d\n\t\tout 0x21, al\n\t\n\tmake_irq_starts_from_intr_40_in_pic_slave:\n\t\tmov al, 40d\n\t\tout 0xa1, al \n\t\n\t; ... ;\n\t\n\ttell_pic_master_where_pic_slave_is_connected:\n\t\tmov al, 04h\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_where_pic_master_is_connected:\n\t\tmov al, 02h\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 01h\n\t\n\ttell_pic_master_the_arch_is_x86:\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_the_arch_is_x86:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 0h\n\t\n\tmake_pic_master_enables_all_irqs:\n\t\tout 0x21, al\n\t\n\tmake_pic_slave_enables_all_irqs:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tret\n\t\nload_idt:\n\tlidt [idtr - start]\n\tret\n\t\nload_task_register:\n    mov ax, 40d\n    ltr ax\n    \n    ret\n\t\nbits 32\nload_page_directory:\n\tmov eax, [page_directory]\n\tmov cr3, eax\n\t\n\tret\n\t\nenable_paging:\n\tmov eax, cr0\n\tor eax, 80000000h\n\tmov cr0, eax\n\t\n\tret\n\t\ndev_write:\n    ; Part 1\n\tpush edx\n\tpush eax\n\t\n    ; Part 2\n\txor edx, edx\n\txor eax, eax\n\t\n    ; Part 3\n\tmov dx, [esp + 12]\n\tmov al, [esp + 16]\n\t\n    ; Part 4\n\tout dx, al \n\t\n    ; Part 5\n\tpop eax\n\tpop edx\n\t\n\tret\n\t\ndev_write_word:\n\tpush edx\n\tpush eax\t\n\t\n    xor edx, edx\n\txor eax, eax\n    \n\tmov dx, [esp + 12]\n\tmov ax, [esp + 16]\n\t\n\tout dx, ax \n\t\n\tpop eax\n\tpop edx\n\t\n\tret\n\t\ndev_read:\n\tpush edx\n\t\n\txor edx, edx\n\txor eax, eax\n\t\n\tmov dx, [esp + 8]\n\t\n\tin ax, dx\n\t\n\tpop edx\n\t\n\tret\n\t\nstart_kernel:\n\tmov eax, 10h\n\tmov ds, eax\n\tmov ss, eax\n    \n\tmov eax, 0h\n\tmov es, eax\n\tmov fs, eax\n\tmov gs, eax\n\t\n\t;sti\n\t\n\tcall kernel_main\n\t\n%include \"gdt.asm\"\n%include \"idt.asm\"\n\ntss:\n    dd 0\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/str.c",
    "content": "#include \"str.h\"\n\nvoid strcpy( char *dest, char *src )\n{\n\tint idx = 0;\n\t\n\twhile ( *src != '\\0' )\n\t{\n\t\tdest[ idx ] = *src;\n\t\t\n\t\tsrc++;\n\t\tidx++;\n\t}\n}\n\nint strcmp( char *str1, char *str2 )\n{\n\twhile ( *str1 != '\\0' )\n\t{\n\t\tif ( *str1 != *str2 )\n\t\t\treturn 0;\n\t\t\n\t\tstr1++;\n\t\tstr2++;\n\t}\n\t\n\tif ( *str2 != '\\0' )\n\t\treturn 0;\n\t\n\treturn 1;\n}\n"
  },
  {
    "path": "evolution_by_versions/06_539kernel_version_ne/str.h",
    "content": "void strcpy( char *, char * );\nint strcmp( char *, char * );\n"
  },
  {
    "path": "src/.gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/c\n# Edit at https://www.gitignore.io/?templates=c\n\n### C ###\n# Prerequisites\n*.d\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n*.bin\n\n# Linker output\n*.ilk\n*.map\n*.exp\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n*.su\n*.idb\n*.pdb\n\n# Kernel Module Compile Results\n*.mod*\n*.cmd\n.tmp_versions/\nmodules.order\nModule.symvers\nMkfile.old\ndkms.conf\n\n# End of https://www.gitignore.io/api/c\n\n*.img\n"
  },
  {
    "path": "src/Makefile",
    "content": "ASM = nasm\nCC = gcc\nBOOTSTRAP_FILE = bootstrap.asm \nSIMPLE_KERNEL = simple_kernel.asm\nINIT_KERNEL_FILES = starter.asm\nKERNEL_FILES = main.c\n\n# -m32 means generate 32-bit code. See \"Machine-Dependent Options\" section in gcc man page for details. Under \"x86 Options\" section \"-m flag\".\n#\n# -Wall:\n#\t\t\t\"This enables all the warnings about constructions that some\n#           users consider questionable, and that are easy to avoid (or\n#           modify to prevent the warning), even in conjunction with\n#           macros.  This also enables some language-specific warnings\n#           described in C++ Dialect Options and Objective-C and\n#           Objective-C++ Dialect Options.\" \n# \t\t\t~ GCC man page\n# \n# -c:\n# \t\t\t\"If any of these options is used [-c, -S, -E], then the linker is not run, and object file names should not be used as arguments.\"\n# \t\t\t~ GCC man page\n#\n# -ffreestanding:\n#\t\t\t\"Assert that compilation targets a freestanding environment.\n#           This implies -fno-builtin.  A freestanding environment is one\n#           in which the standard library may not exist, and program\n#           startup may not necessarily be at \"main\".  The most obvious\n#           example is an OS kernel.  This is equivalent to -fno-hosted.\"\n# \t\t\t~ GCC man page\n#\n# -no-pie:\n#\t\t\t\"Don't produce a dynamically linked position independent executable.\"\n# \t\t\t~ GCC man page\n#\n# -g:\n#\t\t\t\"To tell GCC to emit extra information for use by a debugger, in almost all cases you need only to add -g to your other options.\"\n# \t\t\t~ GCC man page\n#\n# -std=\n#\t\t\t\"Determine the language standard.   This option is currently only supported when compiling C or C++.\"\n#\t\t\tgnu99: \"GNU dialect of ISO C99.  The name gnu9x is deprecated.\"\n#\t\t\tgnu18: \"GNU dialect of ISO C17.  This is the default for C code.\"\n# \t\t\t~ GCC man page\n#-std=gnu99 # -c -Wall -no-pie -g -std=gnu99\nKERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie -fcommon -fno-stack-protector\n#  -O1 -fno-pie \nKERNEL_OBJECT = -o kernel.elf\n\nbuild:\n\techo Please Choose Type\n\nkernel: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\t$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf\n\t$(CC) $(KERNEL_FLAGS) process.c -o process.elf\n\t$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf\n\t$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf\n\t$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf\n\t$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf\n\t$(CC) $(KERNEL_FLAGS) str.c -o str.elf\n\t$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20\n\tdd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046\n\tbochs -f bochs\n\t#qemu-system-x86_64 -s kernel.img\n\ndebug: $(BOOTSTRAP_FILE) $(KERNEL_FILE)\n\t$(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o\n\t$(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o \n\t$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT)\n\t$(CC) $(KERNEL_FLAGS) screen.c -o screen.elf\n\t$(CC) $(KERNEL_FLAGS) process.c -o process.elf\n\t$(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf\n\t$(CC) $(KERNEL_FLAGS) heap.c -o heap.elf\n\t$(CC) $(KERNEL_FLAGS) paging.c -o paging.elf\n\t$(CC) $(KERNEL_FLAGS) ata.c -o ata.elf\n\t$(CC) $(KERNEL_FLAGS) str.c -o str.elf\n\t$(CC) $(KERNEL_FLAGS) filesystem.c -o filesystem.elf\n\tld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf ata.elf str.elf filesystem.elf -o 539kernel.elf\n\tobjcopy -O binary 539kernel.elf 539kernel.bin\n\tdd if=bootstrap.o of=kernel.img\n\tdd seek=1 conv=sync if=539kernel.bin of=kernel.img bs=512 count=20\n\tdd seek=21 conv=sync if=/dev/zero of=kernel.img bs=512 count=2045\n\tbochs -f bochs\n\t\nrerun-debug:\n\tbochs -f bochs\n\nrerun-kernel:\n\tqemu-system-x86_64 -s kernel.img\n\nclean:\n\trm -f *.o\n\trm -f *.elf\n\trm -f *.img\n\trm -f *.bin\n"
  },
  {
    "path": "src/README",
    "content": "[MQH] 25 Nov 2019\nHere is the final code of 539kernel. Any incremental steps, examples and excercises can be found in ../examples.\n"
  },
  {
    "path": "src/ata.c",
    "content": "#include \"ata.h\"\n\nvoid wait_drive_until_ready()\n{\n\tint status = 0;\n\t\n\tdo\n\t{\n\t\tstatus = dev_read( BASE_PORT + 7 );\n\t} while ( ( status ^ 0x80 ) == 128 );\n}\n\n// LBA\nvoid *read_disk( int address )\n{\n\tdev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) ); // Drive 0. Bits 0-3 = Bits 24-27 of LBA\n\tdev_write( BASE_PORT + 2, 1 ); // Sector count\n\tdev_write( BASE_PORT + 3, address & 0x000000FF ); // LBA's 0-7 bits\n\tdev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 ); // LBA's 8-15 bits\n\tdev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 ); // LBA's 16-23 bits\n\tdev_write( BASE_PORT + 7, 0x20 ); // Command: Read with Retry\n\t\n\t// ... //\n\t\n\twait_drive_until_ready();\n\t\n\t// ... //\n\t\n\tshort *buffer = kalloc( SECTOR_SIZE );\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tbuffer[ currByte ] = dev_read( BASE_PORT );\n\t\n\treturn buffer;\n}\n\n// LBA\nvoid write_disk( int address, short *buffer )\n{\n\tdev_write( BASE_PORT + 6, ( 0x0e0 | ( ( address & 0x0F000000 ) >> 24 ) ) ); // Drive 0. Bits 0-3 = Bits 24-27 of LBA\n\tdev_write( BASE_PORT + 2, 1 ); // Sector count\n\tdev_write( BASE_PORT + 3, address & 0x000000FF ); // LBA's 0-7 bits\n\tdev_write( BASE_PORT + 4, ( address & 0x0000FF00 ) >> 8 ); // LBA's 8-15 bits\n\tdev_write( BASE_PORT + 5, ( address & 0x00FF0000 ) >> 16 ); // LBA's 16-23 bits\n\tdev_write( BASE_PORT + 7, 0x30 ); // Command: Write with Retry\n\t\n\twait_drive_until_ready();\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tdev_write_word( BASE_PORT, buffer[ currByte ] );\n\t\t\n\twait_drive_until_ready();\n}\n\n\nvoid *read_disk_chs( int sector )\n{\n\tdev_write( BASE_PORT + 6, 0x0a0 ); // Drive 0 and Head 0\n\tdev_write( BASE_PORT + 2, 1 ); // Sector count\n\tdev_write( BASE_PORT + 3, sector ); // Sector to read\n\tdev_write( BASE_PORT + 4, 0 ); // Cylinder - Low\n\tdev_write( BASE_PORT + 5, 0 ); // Cylinder - High\n\tdev_write( BASE_PORT + 7, 0x20 ); // Command: Read with Retry\n\t\n\t// ... //\n\t\n\twait_drive_until_ready();\n\t\n\t// ... //\n\t\n\tshort *buffer = kalloc( SECTOR_SIZE );\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tbuffer[ currByte ] = dev_read( BASE_PORT );\n\n\treturn buffer;\n}\n\nvoid write_disk_chs( int sector, short *buffer )\n{\n\tdev_write( BASE_PORT + 6, 0x0a0 ); // Drive 0 and Head 0\n\tdev_write( BASE_PORT + 2, 1 ); // Sector count\n\tdev_write( BASE_PORT + 3, sector ); // Sector to read\n\tdev_write( BASE_PORT + 4, 0 ); // Cylinder - Low\n\tdev_write( BASE_PORT + 5, 0 ); // Cylinder - High\n\tdev_write( BASE_PORT + 7, 0x30 ); // Command: Write with Retry\n\t\n\t// ... //\n\t\n\twait_drive_until_ready();\n\t\n\t// ... //\n\t\n\tfor ( int currByte = 0; currByte < ( SECTOR_SIZE / 2 ); currByte++ )\n\t\tdev_write_word( BASE_PORT, buffer[ currByte ] );\n\t\n\t// ... //\n\t\n\twait_drive_until_ready();\n}\n\n\n"
  },
  {
    "path": "src/ata.h",
    "content": "#define BASE_PORT 0x1F0\n#define SECTOR_SIZE 512\n\nvoid wait_drive_until_ready();\n\nvoid *read_disk( int );\nvoid write_disk( int, short * );\n\nvoid *read_disk_chs( int );\nvoid write_disk_chs( int, short * );\n"
  },
  {
    "path": "src/bochs",
    "content": "# configuration file generated by Bochs\nplugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1\nconfig_interface: textconfig\ndisplay_library: x, options=\"gui_debug\"\nmemory: host=32, guest=32\nromimage: file=\"/usr/share/bochs/BIOS-bochs-latest\"\nvgaromimage: file=\"/usr/share/bochs/VGABIOS-lgpl-latest\"\nboot: disk\nfloppy_bootsig_check: disabled=0\n# no floppya\n# no floppyb\nata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14\nata0-master: type=disk, mode=flat, translation=auto, path=\"kernel.img\", cylinders=2, heads=16, spt=63, biosdetect=auto, model=\"Generic 1234\"\nata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15\nata2: enabled=0\nata3: enabled=0\npci: enabled=1, chipset=i440fx\nvga: extension=vbe, update_freq=5\ncpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0\ncpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=sse2, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, avx=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, tbm=0, fma4=0, vmx=1, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1\ncpuid: vendor_string=\"GenuineIntel\"\ncpuid: brand_string=\"              Intel(R) Pentium(R) 4 CPU        \"\n\nprint_timestamps: enabled=0\ndebugger_log: -\nmagic_break: enabled=0\nport_e9_hack: enabled=0\nprivate_colormap: enabled=0\nclock: sync=none, time0=local, rtc_sync=0\n# no cmosimage\n# no loader\nlog: -\nlogprefix: %t%e%d\npanic: action=ask\nerror: action=report\ninfo: action=report\ndebug: action=ignore\nkeyboard: type=mf, serial_delay=250, paste_delay=100000, keymap=\nuser_shortcut: keys=none\nmouse: enabled=0, type=ps2, toggle=ctrl+mbutton\nparport1: enabled=1, file=\"\"\nparport2: enabled=0\ncom1: enabled=1, mode=null, dev=\"\"\ncom2: enabled=0\ncom3: enabled=0\ncom4: enabled=0\n"
  },
  {
    "path": "src/bootstrap.asm",
    "content": "start:\n\t; [MQH] 3 Sep 2019\n\t; When a the boot sector is loaded by BIOS. It will be loaded on the location 07C0h in the memory.\n\t; What we do here is setting the register \"ds\" to the value \"07C0\" which is the same of the memory address we are on now.\n\t; Our variable \"hello_string\" will be loaded as a part of the bootloader, when we use it in the line \"mov si, hello_string\"\n\t; we're actually loading the memory address of the first character, let's assume that this memory address is (1000). Because\n\t; it is considered as a \"data\" by the processor. This offset (the memory address of \"hello_string\") will be added to the data segment\n\t; selector which resides in the register \"ds\". According to \"Protected Mode Software Architecture\", the initial value of \"ds\" is 0000h,\n\t; so, if we keep \"ds\" as it is, the CPU is going to load the data from the memory 00001000, BUT we are actually on 07C0, so the data\n\t; segment selector should be 07C0h so we can get the correct address of \"hello_string\" which is 07C01000 and not 00001000.\n\t; For backward compatibility, when the bootloader starts, the execution environment will be in \"Real Mode\", 16-bit.\n\tmov ax, 07C0h\n\tmov ds, ax\n\t\t\n\t; ... ;\n\t\n\t; == Printing == ;\n\t\n\tmov si, title_string\n\tcall print_string ; \"CALL\" is used instead of \"JMP\" because we would like to return to the next instruction after \"print_string\" finishes.\n\t\n\tmov si, message_string\n\tcall print_string\n\t\n\t; ... ;\n\t\n\t; === Loading the Kernel === ;\n\t\n\tcall load_kernel_from_disk\n\t\n\t; If the loading has been performed correctly. Jump to the kernel's code which resides on 0900h:0000 according\n\t; to ES:BX values before calling (int 13h).\n\t;\n\t; There is a difference between \"JMP\" and \"CALL\" inctructions. The first one doesn't store returning information\n\t; in the stack while the later does. Because we are not going to return from kernel to the bootloader, we don't\n\t; need to store return information.\n\t\n\tjmp 0900h:0000\n\n; ... ;\n; ... ;\n\nload_kernel_from_disk:\t\n\t; [MQH] 26 Nov 2019\n\t; BIOS provides disk services through intrrupt 13h. The value of the register \"ah\" decides which disk service that we are requesting from BIOS.\n\t\n\t; The Disk Service \"02h\" loads sectors to the memory. The memory location that we would like to load our kernel in should be decided\n\t; before calling \"int 13h\". There are two parts of this location. The first part (segment selector) resides in the register \"ES\" while \n\t; the other part (offset) resides in the register \"BX\".\n\t;\n\t; x86 Segment Registers:    CS: for code segment. \n\t;                           DS, ES, FS, and GS: for 4 data segments.\n\t;                           SS: for stack segment.\n\t; They are 16-bit registers that hold \"segment selectors\"\n\tmov ax, [curr_sector_to_load]\n\tsub ax, 2\n\tmov bx, 512d\n\tmul bx\n\tmov bx, ax\n\t\n\tmov ax, 0900h\n\tmov es, ax\n\t\n\tmov ah, 02h     ; Requesting the service of reading disk sectors\n\tmov al, 1h    \t; Number of sectors to read (How many sectors to read?)\n\tmov ch, 0h      ; Track number\n\tmov cl, [curr_sector_to_load]     ; Sector number\n\tmov dh, 0h      ; Head number\n\tmov dl, 80h     ; Drive to read from. (0 = Floppy. 80h = Drive #0. 81h = Drive #1)\n\tint 13h         ; BIOS Disk Services\n\t\n\t\n\t; The instruction \"jc\" jumps to a memory location when CF = 1 (jc = jump if carry).\n\t; CF (or carry flag) is the first bit of EFLAG register in x86. The BIOS service (13h,02h)\n\t; clear CF (that is, put 0 in CF) when everything is fine. But if there is some error\n\t; it's going to set CF (that is, put 1 in CF). Error code will be in \"ah\".\n\t;\n\t; If any error happens in loading our kernel. The bootloader is going to jump to the label \"kernel_load_error\".\n\tjc kernel_load_error\n\t\n\tsub byte [number_of_sectors_to_load], 1\n\tadd byte [curr_sector_to_load], 1\n\tcmp byte [number_of_sectors_to_load], 0\n\t\n\tjne load_kernel_from_disk\n\t\n\tret\n\n; When the bootloader fails to load the kernel. A nice message is printted for the user.\nkernel_load_error:\n\tmov si, load_error_string\n\tcall print_string\n\t\n\t; \"$\" is a special expression in NASM. It means the starting memory address (or assembly position?) of current instruction, that means\n\t; the following instruction is going to loop forever. \n\tjmp $\n\n; ... ;\n; ... ;\n\n; [MQH] 3 Sep 2019\n; BIOS provides video services through intrrupt 10h. The value of the register \"ah\" decides which video service that we are requesting from BIOS.\n; Those BIOS services are only available on Real Mode (https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode)\n;\n; ah = 0Eh means that we wish to print a character in TTY mode.\n; For an example of using service \"0Eh\" to print \"Hello\" character by character, please refer to \"../examples/bootstrap/1/\".\n\t\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n    ; [MQH] 26 Nov 2019\n\t; It's known that a byte = 8 bits. In x86 there are more two units: a \"word\" = 16 bits and \"doubleword\" = 32 bits. Some x86 instructions have multiple variants that work\n\t; with a specific aforementioned unit. \"lods\" is an example of these instructions, there is \"lodsb\" which works with a byte, \"lodsw\" which works with a word and \"lodsd\" which\n\t; works with doubleword.\n\t;\n\t; The instruction \"lods\" uses the value which is stored in register \"si\" (when using lodsb or loadsw) or register \"esi\" (when using lodsw) and assume that this\n\t; value as memory location. Then according to the used unit a (b)yte (8-bits), (w)ord (16-bits) or (d)oubleword (32-bit) will be read from the memory location DS:(E)SI\n\t; and store these bits in al, ax or eax according to the size of read data.\n\tlodsb\n\t\n\tcmp al, 0\n\tje printing_finished\n\t\n\tint 10h\n\n\tjmp print_char\n\nprinting_finished:\n    mov al, 10d ; Print new line\n    int 10h\n    \n    ; [MQH] NEW 25 June 2021\n    ; Move the cursor to the beginning\n    mov ah, 03h\n\tmov bh, 0\n\tint 10h\n\t\n\tmov ah, 02h\n\tmov dl, 0\n\tint 10h\n    \n    ; print_string is a procedure (or function), therefore we should return. It is called by using \"CALL\" instead of \"JMP\".\n\tret\n\n; ... ;\n\n; [MQH] 9 Dec 2019\n; \"DB\" is one of pseudo-instructions which is provided by NASM. A source line in NASM follows the following format\n; label: instruction operands ; comment\n; The label is optional and even the colon after the label is optional.\n; \"DB\" is used to declare initialized data. The \"B\" in \"DB\" means byte.\n; the part \", 0\" means that the last byte will be 0. In some way resembles\n; nul character in C strings.\n;\n; Put the string in the output of this assembly file. Byte by byte, and the address of\n; this string will be in the label, so we can reach the string inside the assembly source code.\ntitle_string        \t\tdb  'The Bootloader of 539kernel.', 0\nmessage_string      \t\tdb  'The kernel is loading...', 0\nload_error_string   \t\tdb  'The kernel cannot be loaded', 0\nnumber_of_sectors_to_load \tdb \t15d ; 255 sectors = 127.5KB ; [MQH] NEW 4 July 2021\ncurr_sector_to_load \t\tdb \t2d\n\n; [MQH] 9 Dec 2019\n; \"TIMES\" is an NASM pseudo-instruction which repeats an instruction a number of specific times.\n; The first operand of \"TIMES\" is the number of repetitions.\n; As we mentioned before \"$\" means the starting address (or assembly position?) of current instruction.\n; \"$$\" is another special expression which means the starting address (or assembly position?) of current section.\n; So, we know that the size of bootstrap should be 512 byte. Two bytes are represent the magic code in the last line\n; so 510 bytes remains for us. Our code starts from position $$ and we reached position $. Therefore, $ - $$ gives\n; us the size of our code. So, 510 - ( $ - $$ ) gives us the remaining size of the 512 bytes and fills it with zeros\n; by using \"DB\".\ntimes 510-($-$$) db 0\n\n; Put the magic code of bootloader in the end of assembly file's output. \"W\" means word.\ndw 0xAA55\n"
  },
  {
    "path": "src/filesystem.c",
    "content": "#include \"filesystem.h\"\n\nvoid filesystem_init()\n{\n\tbase_block = read_disk( BASE_BLOCK_ADDRESS );\n}\n\nvoid update_base_block( int new_head, int new_tail )\n{\n\tbase_block->head = new_head;\n\tbase_block->tail = new_tail;\n\t\n\twrite_disk( BASE_BLOCK_ADDRESS, base_block );\n}\n\nmetadata_t *load_metadata( int address )\n{\n\tmetadata_t *metadata = read_disk( address );\n\t\n\treturn metadata;\n}\n\nint get_files_number()\n{\n\tif ( base_block->head == 0 )\n\t\treturn 0;\n\t\n\tint files_number = 0;\n\t\n\t// ... //\n\t\n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\t\n\twhile ( 1 )\n\t{\n\t\tfiles_number++;\n\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\n\t}\n\t\n\treturn files_number;\n}\n\nvoid create_file( char *filename, char *buffer )\n{\n\tint metadata_lba = ( base_block->head == 0 ) ? BASE_BLOCK_ADDRESS + 1 : base_block->tail + 2;\n\tint file_lba = metadata_lba + 1;\n\t\n\tmetadata_t *metadata = kalloc( sizeof( metadata_t ) );\n\t\n\tmetadata->next_file_address = 0;\n\t\n\t// ... //\n\t\n\tint currIdx;\n\t\n\tfor ( currIdx = 0; *filename != '\\0' && currIdx < FILENAME_LENGTH - 1; currIdx++, filename++ )\n\t\tmetadata->filename[ currIdx ] = *filename;\n\t\n\tmetadata->filename[ currIdx ] = '\\0';\n\t\n\t// ... //\n\t\n\twrite_disk( metadata_lba, metadata );\n\twrite_disk( file_lba, buffer );\n\t\n\t// ... //\n\t\n\tif ( base_block->head == 0 )\n\t{\n\t\tupdate_base_block( metadata_lba, metadata_lba );\n\t}\n\telse\n\t{\n\t\tmetadata_t *tail_metadata = load_metadata( base_block->tail );\n\t\t\n\t\ttail_metadata->next_file_address = metadata_lba;\n\t\t\n\t\twrite_disk( base_block->tail, tail_metadata );\t\t\n\t\tupdate_base_block( base_block->head, metadata_lba );\n\t}\n}\n\nchar **list_files()\n{\n\tif ( base_block->head == 0 )\n\t\treturn -1;\n\t\n\tchar **list;\n\t\n\tlist = kalloc( get_files_number() * sizeof( char * ) );\n\t\t\n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\t\n\tint idx = 0;\n\t\n\twhile ( 1 )\n\t{\n\t\tlist[ idx ] = curr_file->filename;\n\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\n\t\t\n\t\tidx++;\n\t}\n\t\n\treturn list;\n}\n\nint get_address_by_filename( char *filename )\n{\n\tmetadata_t *curr_file = load_metadata( base_block->head );\n\tint curr_file_address = base_block->head;\n\t\n\tint idx = 0;\n\t\n\twhile ( 1 )\n\t{\n\t\tif ( strcmp( curr_file->filename, filename ) == 1 )\n\t\t\treturn curr_file_address;\n\t\t\t\n\t\tif ( curr_file->next_file_address == 0 )\n\t\t\tbreak;\n\t\t\n\t\tcurr_file_address = curr_file->next_file_address;\n\t\tcurr_file = load_metadata( curr_file->next_file_address );\t\t\n\t}\n\t\n\treturn 0;\n}\n\nchar *read_file( char *filename )\n{\n\tint address = get_address_by_filename( filename );\n\t\n\tif ( address == 0 )\n\t\treturn 0;\n\t\n\tprinti( address );\n\t\n\tchar *buffer = read_disk( address + 1 );\n\t\n\treturn buffer;\n}\n\nint get_prev_file_address( int address )\n{\n\tmetadata_t *prev_file = load_metadata( base_block->head );\n\tint prev_file_address = base_block->head;\n\n\twhile ( 1 )\n\t{\n\t\tif ( prev_file->next_file_address == address )\n\t\t\treturn prev_file_address;\n\t\t\n\t\tprev_file_address = prev_file->next_file_address;\n\t\tprev_file = load_metadata( prev_file->next_file_address );\n\t}\n\t\t\n\treturn -1;\n}\n\nvoid delete_file( char *filename )\n{\n\tint curr_file_address = get_address_by_filename( filename );\n\t\n\tif ( curr_file_address == 0 )\n\t\treturn;\n\t\t\n\t// ... //\n\t\n\tif ( get_files_number() == 1 )\n\t{\n\t\tupdate_base_block( 0, 0 );\n\t\t\n\t\treturn;\n\t}\n\t\t\t\n\tmetadata_t *curr_file_metadata = read_disk( curr_file_address );\n\t\n\tif ( curr_file_address == base_block->head )\n\t{\n\t\tupdate_base_block( curr_file_metadata->next_file_address, base_block->tail );\n\t}\n\telse\n\t{\n\t\tint prev_file_address = get_prev_file_address( curr_file_address );\n\t\t\n\t\tmetadata_t *prev_file = load_metadata( prev_file_address );\n\n\t\tprev_file->next_file_address = curr_file_metadata->next_file_address;\n\t\t\n\t\twrite_disk( prev_file_address, prev_file );\n\t\t\n\t\tif ( curr_file_address == base_block->tail )\n\t\t\tupdate_base_block( base_block->head, prev_file_address );\n\t}\n}\n"
  },
  {
    "path": "src/filesystem.h",
    "content": "#define BASE_BLOCK_ADDRESS 100\n#define FILENAME_LENGTH 256\n\ntypedef struct\n{\n\tint head, tail;\n} base_block_t;\n\ntypedef struct\n{\n\tchar filename[ FILENAME_LENGTH ];\n\tint next_file_address;\n} metadata_t;\n\nbase_block_t *base_block;\n\nvoid filesystem_init();\nvoid create_file( char *, char * );\nchar **list_files();\nchar *read_file( char * );\n\n// Auxiliary Functions\nmetadata_t *load_metadata( int );\nint get_address_by_filename( char * );\nint get_prev_file_address( int );\nint get_files_number();\n"
  },
  {
    "path": "src/gdt.asm",
    "content": "; The values of the decriptors from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel)\ngdt:\n\tnull_descriptor\t\t\t\t: \tdw 0, 0, 0, 0\n\tkernel_code_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9a00, 0x00cf\n\tkernel_data_descriptor\t\t: \tdw 0xffff, 0x0000, 0x9200, 0x00cf\n\tuserspace_code_descriptor\t: \tdw 0xffff, 0x0000, 0xfa00, 0x00cf\n\tuserspace_data_descriptor\t: \tdw 0xffff, 0x0000, 0xf200, 0x00cf\n\t; DON'T FORGET TO CHANGE THE SIZE OF THE GDT\n\t; TODO: I think the limit isn't correct\n\ttss_descriptor\t\t\t\t:\tdw tss + 3, tss, 0x8900, 0x0000\n\ngdtr:\n\tgdt_size_in_bytes\t: \tdw ( 6 * 8 ) ;= 28h\n\tgdt_base_address\t: \tdd gdt\n\n"
  },
  {
    "path": "src/heap.c",
    "content": "#include \"heap.h\"\n\nvoid heap_init()\n{\n\theap_base = 0x100000;\n}\n\nint kalloc( int bytes )\n{\n\t// Note: Not necessarily page-aligned\n\t\n\tunsigned int new_object_address = heap_base;\n\t\n\theap_base += bytes;\n\t\n\treturn new_object_address;\n}\n"
  },
  {
    "path": "src/heap.h",
    "content": "unsigned int heap_base;\n\nvoid heap_init();\nint kalloc( int );\n"
  },
  {
    "path": "src/idt.asm",
    "content": "isr_0:\n\tcli\n\tpush 0\n\tjmp isr_basic\n\nisr_1:\n\tcli\n\tpush 1\n\tjmp isr_basic\n\t\nisr_2:\n\tcli\n\tpush 2\n\tjmp isr_basic\n\t\nisr_3:\n\tcli\n\tpush 3\n\tjmp isr_basic\n\t\nisr_4:\n\tcli\n\tpush 4\n\tjmp isr_basic\n\t\nisr_5:\n\tcli\n\tpush 5\n\tjmp isr_basic\n\t\nisr_6:\n\tcli\n\tpush 6\n\tjmp isr_basic\n\t\nisr_7:\n\tcli\n\tpush 7\n\tjmp isr_basic\n\t\nisr_8:\n\tcli\n\tpush 8\n\tjmp isr_basic\n\t\nisr_9:\n\tcli\n\tpush 9\n\tjmp isr_basic\n\t\nisr_10:\n\tcli\n\tpush 10\n\tjmp isr_basic\n\t\nisr_11:\n\tcli\n\tpush 11\n\tjmp isr_basic\n\t\nisr_12:\n\tcli\n\tpush 12\n\tjmp isr_basic\n\t\nisr_13:\n\tcli\n\tpush 13\n\tjmp isr_basic\n\t\nisr_14:\n\tcli\n\tpush 14\n\tjmp isr_basic\n\t\nisr_15:\n\tcli\n\tpush 15\n\tjmp isr_basic\n\t\nisr_16:\n\tcli\n\tpush 16\n\tjmp isr_basic\n\t\nisr_17:\n\tcli\n\tpush 17\n\tjmp isr_basic\n\t\nisr_18:\n\tcli\n\tpush 18\n\tjmp isr_basic\n\t\nisr_19:\n\tcli\n\tpush 19\n\tjmp isr_basic\n\t\nisr_20:\n\tcli\n\tpush 20\n\tjmp isr_basic\n\t\nisr_21:\n\tcli\n\tpush 21\n\tjmp isr_basic\n\nisr_22:\n\tcli\n\tpush 22\n\tjmp isr_basic\n\t\nisr_23:\n\tcli\n\tpush 23\n\tjmp isr_basic\n\t\nisr_24:\n\tcli\n\tpush 24\n\tjmp isr_basic\n\t\nisr_25:\n\tcli\n\tpush 25\n\tjmp isr_basic\n\t\nisr_26:\n\tcli\n\tpush 26\n\tjmp isr_basic\n\t\nisr_27:\n\tcli\n\tpush 27\n\tjmp isr_basic\n\t\nisr_28:\n\tcli\n\tpush 28\n\tjmp isr_basic\n\t\nisr_29:\n\tcli\n\tpush 29\n\tjmp isr_basic\n\t\nisr_30:\n\tcli\n\tpush 30\n\tjmp isr_basic\n\t\nisr_31:\n\tcli\n\tpush 31\n\tjmp isr_basic\n\t\n; System Timer\nisr_32:\n\t\n\tcli\n\t\n\tpusha ; Store the context of current process\n\t\n\tmov eax, [esp + 32] ; EIP before interrupt. Could be the EIP of the current process\n\tpush eax  \n\t\n\tcall scheduler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tadd esp, 40d ; Remove return address from stack, EIP and all general purpose registers of previous process.\n\tpush run_next_process\n\n\tiret\n\t\nisr_33:\n\tcli\n\tpush 33\n\tjmp irq_basic\n\t\nisr_34:\n\tcli\n\tpush 34\n\tjmp irq_basic\n\t\nisr_35:\n\tcli\n\tpush 35\n\tjmp irq_basic\n\t\nisr_36:\n\tcli\n\tpush 36\n\tjmp irq_basic\n\t\nisr_37:\n\tcli\n\tpush 37\n\tjmp irq_basic\n\nisr_38:\n\tcli\n\tpush 38\n\tjmp irq_basic\n\nisr_39:\n\tcli\n\tpush 39\n\tjmp irq_basic\n\nisr_40:\n\tcli\n\tpush 40\n\tjmp irq_basic\n\nisr_41:\n\tcli\n\tpush 41\n\tjmp irq_basic\n\nisr_42:\n\tcli\n\tpush 42\n\tjmp irq_basic\n\nisr_43:\n\tcli\n\tpush 43\n\tjmp irq_basic\n\nisr_44:\n\tcli\n\tpush 44\n\tjmp irq_basic\n\nisr_45:\n\tcli\n\tpush 45\n\tjmp irq_basic\n\nisr_46:\n\tcli\n\tpush 46\n\tjmp irq_basic\n\nisr_47:\n\tcli\n\tpush 47\n\tjmp irq_basic\n\t\nisr_48:\n\tcli\n\tpush 48\n\tjmp irq_basic\n\nisr_basic:\n;\tcli\n\tcall interrupt_handler\n\t\n\tpop eax\n\tsti\n\tiret\n\t\nirq_basic:\n;\tcli\n\tcall interrupt_handler\n\t\n\tmov al, 0x20\n\tout 0x20, al\n\t\n\tcmp byte [esp], 40d ; Interrupt number\n\tjnge irq_basic_end\n\t\n\tmov al, 0xa0\n\tout 0x20, al\n\t\n\tirq_basic_end:\n\t\tpop eax\n\t\tsti\n\t\tiret\n\t\n; The value of the flags from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel)\nidt:\n\tdw isr_0, 8, 0x8e00, 0x0000\n\tdw isr_1, 8, 0x8e00, 0x0000\n\tdw isr_2, 8, 0x8e00, 0x0000\n\tdw isr_3, 8, 0x8e00, 0x0000\n\tdw isr_4, 8, 0x8e00, 0x0000\n\tdw isr_5, 8, 0x8e00, 0x0000\n\tdw isr_6, 8, 0x8e00, 0x0000\n\tdw isr_7, 8, 0x8e00, 0x0000\n\tdw isr_8, 8, 0x8e00, 0x0000\n\tdw isr_9, 8, 0x8e00, 0x0000\n\tdw isr_10, 8, 0x8e00, 0x0000\n\tdw isr_11, 8, 0x8e00, 0x0000\n\tdw isr_12, 8, 0x8e00, 0x0000\n\tdw isr_13, 8, 0x8e00, 0x0000\n\tdw isr_14, 8, 0x8e00, 0x0000\n\tdw isr_15, 8, 0x8e00, 0x0000\n\tdw isr_16, 8, 0x8e00, 0x0000\n\tdw isr_17, 8, 0x8e00, 0x0000\n\tdw isr_18, 8, 0x8e00, 0x0000\n\tdw isr_19, 8, 0x8e00, 0x0000\n\tdw isr_20, 8, 0x8e00, 0x0000\n\tdw isr_21, 8, 0x8e00, 0x0000\n\tdw isr_22, 8, 0x8e00, 0x0000\n\tdw isr_23, 8, 0x8e00, 0x0000\n\tdw isr_24, 8, 0x8e00, 0x0000\n\tdw isr_25, 8, 0x8e00, 0x0000\n\tdw isr_26, 8, 0x8e00, 0x0000\n\tdw isr_27, 8, 0x8e00, 0x0000\n\tdw isr_28, 8, 0x8e00, 0x0000\n\tdw isr_29, 8, 0x8e00, 0x0000\n\tdw isr_30, 8, 0x8e00, 0x0000\n\tdw isr_31, 8, 0x8e00, 0x0000\n\tdw isr_32, 8, 0x8e00, 0x0000\n\tdw isr_33, 8, 0x8e00, 0x0000\n\tdw isr_34, 8, 0x8e00, 0x0000\n\tdw isr_35, 8, 0x8e00, 0x0000\n\tdw isr_36, 8, 0x8e00, 0x0000\n\tdw isr_37, 8, 0x8e00, 0x0000\n\tdw isr_38, 8, 0x8e00, 0x0000\n\tdw isr_39, 8, 0x8e00, 0x0000\n\tdw isr_40, 8, 0x8e00, 0x0000\n\tdw isr_41, 8, 0x8e00, 0x0000\n\tdw isr_42, 8, 0x8e00, 0x0000\n\tdw isr_43, 8, 0x8e00, 0x0000\n\tdw isr_44, 8, 0x8e00, 0x0000\n\tdw isr_45, 8, 0x8e00, 0x0000\n\tdw isr_46, 8, 0x8e00, 0x0000\n\tdw isr_47, 8, 0x8e00, 0x0000\n\tdw isr_48, 8, 0x8e00, 0x0000\n\t\nidtr:\n\tidt_size_in_bytes\t: \tdw idtr - idt\n\tidt_base_address\t: \tdd idt\n"
  },
  {
    "path": "src/linker.ld",
    "content": "/* Based on: http://www.jamesmolloy.co.uk/tutorial_html/1.-Environment%20setup.html */\n\nSECTIONS\n{\n  .text 0x09000 :\n  {\n    code = .; _code = .; __code = .;\n    *(.text)\n    /*. = ALIGN(4096);*/\n  }\n\n  .data :\n  {\n     data = .; _data = .; __data = .;\n     *(.data)\n     *(.rodata)\n     /*. = ALIGN(4096);*/\n  }\n\n  .bss :\n  {\n    bss = .; _bss = .; __bss = .;\n    *(.bss)\n    /*. = ALIGN(4096);*/\n  }\n\n  end = .; _end = .; __end = .;\n} \n"
  },
  {
    "path": "src/main.c",
    "content": "#include \"heap.h\"\n#include \"paging.h\"\n#include \"screen.h\"\n#include \"scheduler.h\"\n#include \"ata.h\"\n#include \"filesystem.h\"\n#include \"str.h\"\n\nvoid processA();\nvoid processB();\nvoid processC();\nvoid processD();\n\nvoid print_fs()\n{\n\tchar **files = list_files();\n\n\tfor ( int currIdx = 0; currIdx < get_files_number(); currIdx++ )\n\t{\n\t\tprint( \"File: \" );\n\t\tprint( files[ currIdx ] );\n\t\tprintln();\n\t}\n\t\n\tprint( \"==\" );\n\tprintln();\n}\n\nvoid kernel_main()\n{\t\n\theap_init();\n\tpaging_init();\t\n\tscreen_init();\n\tprocess_init();\n\tscheduler_init();\n\tfilesystem_init();\n\t\n\t// ... //\n\t\n\tprint( \"Welcome to 539kernel!\" );\n\tprintln();\n\tprint( \"We are now in Protected-mode\" );\n\tprintln();\n\tprinti( 539 );\n\tprintln();\n\t\n\t// ... //\n\t\n\tchar *data = kalloc( 512 );\n\tstrcpy( data, \"The content of the first file on 539filesystem\" );\t\n\tcreate_file( \"first_file\", data );\n\t\n\t// ... //\n\t\n\tchar *data2 = kalloc( 512 );\n\tstrcpy( data2, \"SECOND FILE in 539filesystem\" );\n\tcreate_file( \"second_file\", data2 );\n\t\n\t// ... //\n\t\n\tchar *data3 = kalloc( 512 );\n\tstrcpy( data3, \"THIRD FILE in 539filesystem\" );\n\tcreate_file( \"third_file\", data3 );\n\t\n\t// ... //\n\t\n\tchar *data4 = kalloc( 512 );\n\tstrcpy( data4, \"FOURTH FILE in 539filesystem\" );\n\tcreate_file( \"fourth_file\", data4 );\n\t\n\t// ... //\n\t\n\t//print_fs();\n\t\n\t//delete_file( \"first_file\" );\n\t//print_fs();\n\t\n\t//delete_file( \"second_file\" );\n\t//print_fs();\n\t\n\t//delete_file( \"third_file\" );\n\t//print_fs();\n\t\n\t//delete_file( \"fourth_file\" );\n\t//print_fs();\n\t\n\n\t\n\t\n\t// ... //\n\t\n\tprint( read_file( \"first_file\" ) ); println();\n\tprint( read_file( \"second_file\" ) ); println();\n\tprint( read_file( \"third_file\" ) ); println();\n\tprint( read_file( \"fourth_file\" ) ); println();\n\t\n\t// ... //\n\t\n\n\t\n\t/*void *data = //read_disk_chs( 1 ); \n\t\t\t\tread_disk( 100 );\n\t\n\tprinti( data );*/\n\t\n\t\n\t/*\n\tchar *data = kalloc( 512 );\n\t\n\tfor ( int currIdx = 0; currIdx < 512; currIdx++ )\n\t\tdata[ currIdx ] = 'X';\n\t\n\tdata[ 511 ] = 'D';\n\t\n\twrite_disk( 0, data );\n\n\tchar *data2 = kalloc( 512 );\n\t\n\tfor ( int currIdx = 0; currIdx < 512; currIdx++ )\n\t\tdata2[ currIdx ] = 'Y';\n\t\n\tdata2[ 511 ] = 'D';\n\t\t\n\twrite_disk( 1, data2 );\n\t\n\tchar *data3 = kalloc( 512 );\n\t\n\tfor ( int currIdx = 0; currIdx < 512; currIdx++ )\n\t\tdata3[ currIdx ] = 'Z';\n\t\n\tdata3[ 511 ] = 'D';\n\t\t\n\twrite_disk( 2, data3 );\n\t\n\tread_disk( 0 );\n\tread_disk( 1 );\n\tread_disk( 2 );\n\t*/\n\t\n\t\n//\twrite_disk_chs( 1, data );\n\t/*\n\tprintln();\n\tprint( \"=============\" );\n\t*/\n\t/*process_create( &processA );\n\tprocess_create( &processB );\n\tprocess_create( &processC );\n\tprocess_create( &processD );\n\t\n\tasm( \"sti\" );*/\n\t\n\twhile( 1 );\n}\n\nvoid interrupt_handler( int interrupt_number )\n{\n\tprint( \"Interrupt Received \" );\n\tprinti( interrupt_number );\n\tprintln();\n}\n\nvoid processA()\n{\n\tprint( \"Process A,\" );\n\n\twhile ( 1 )\n\t\tasm( \"mov $5390, %eax\" );\n}\n\nvoid processB()\n{\n\tprint( \"Process B,\" );\n\n\twhile ( 1 )\n\t\tasm( \"mov $5391, %eax\" );\n}\n\nvoid processC()\n{\n\tprint( \"Process C,\" );\n\n\twhile ( 1 )\n\t\tasm( \"mov $5392, %eax\" );\n}\n\nvoid processD()\n{\n\tprint( \"Process D,\" );\n\n\twhile ( 1 )\n\t\tasm( \"mov $5393, %eax\" );\n}\n"
  },
  {
    "path": "src/paging.c",
    "content": "#include \"paging.h\"\n\nvoid paging_init()\n{\n\t// Initializing Kernel's Page Directory (1 to 1 mapping)\n\t\n\tunsigned int curr_page_frame = 0;\n\t\n\t// We allocate 4 * 1024 bytes here, whatever the size of\n\t// the page directory, to make sure that the page tables\n\t// that are coming next are in page aligned-addresses.\n\tpage_directory = kalloc( 4 * 1024 );\n\t\t\n\tfor ( int currPDE = 0; currPDE < PDE_NUM; currPDE++ )\n\t{\n\t\tunsigned int *pagetable = kalloc( 4 * PTE_NUM );\n\t\t\n\t\tfor ( int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++ )\n\t\t\tpagetable[ currPTE ] = create_page_entry( curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t\t\n\t\tpage_directory[ currPDE ] = create_page_entry( pagetable, 1, 0, 0, 1, 1, 0, 0, 0 );\n\t}\n\n\t// ... //\n\t\n\tload_page_directory();\n\tenable_paging();\n}\n\nint create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char write_through_cache, char accessed, char page_size, char dirty )\n{\n\tint entry = 0;\n\t\n\tentry |= present;\n\tentry |= writable << 1;\n\tentry |= privilege_level << 2;\n\tentry |= write_through_cache << 3;\n\tentry |= cache_enabled << 4;\n\tentry |= accessed << 5;\n\tentry |= dirty << 6;\n\tentry |= page_size << 7;\n\t\n\treturn base_address | entry;\n}\n\n\n"
  },
  {
    "path": "src/paging.h",
    "content": "#define PDE_NUM 3\n#define PTE_NUM 1024\n\nextern void load_page_directory();\nextern void enable_paging();\n\nunsigned int *page_directory;\n\nvoid paging_init();\nint create_page_entry( int, char, char, char, char, char, char, char, char );\n"
  },
  {
    "path": "src/process.c",
    "content": "#include \"process.h\"\n\nvoid process_init()\n{\n\tprocesses_count = 0;\n\tcurr_pid = 0;\n}\n\nprocess_t *process_create( int *base_address )\n{\n\tprocess_t *process = kalloc( sizeof( process_t ) );\n\t\n\tprocess->pid = curr_pid++;\n\t\n\tprocess->context.eax = 0;\n\tprocess->context.ecx = 0;\n\tprocess->context.edx = 0;\n\tprocess->context.ebx = 0;\n\tprocess->context.esp = 0;\n\tprocess->context.ebp = 0;\n\tprocess->context.esi = 0;\n\tprocess->context.edi = 0;\n\tprocess->context.eip = base_address;\n\t\n\tprocess->state = READY;\n\tprocess->base_address = base_address;\n\t\n\tprocesses[ process->pid ] = process;\n\t\n\tprocesses_count++;\n\t\n\treturn process;\n}\n\n\n"
  },
  {
    "path": "src/process.h",
    "content": "typedef enum process_state { READY, RUNNING } process_state_t;\n\ntypedef struct process_context\n{\n\tint eax, ecx, edx, ebx, esp, ebp, esi, edi, eip;\n} process_context_t;\n\ntypedef struct process\n{\n\tint pid;\n\tprocess_context_t context;\n\tprocess_state_t state;\n\tint *base_address;\n} process_t;\n\nprocess_t *processes[ 15 ]; // TODO: Dynamic\nint processes_count, curr_pid;\n\nvoid process_init();\nprocess_t *process_create( int * );\n"
  },
  {
    "path": "src/scheduler.c",
    "content": "#include \"scheduler.h\"\n\nvoid scheduler_init()\n{\n\tnext_sch_pid = 0;\n\tcurr_sch_pid = 0;\n}\n\nprocess_t *get_next_process()\n{\n\tprocess_t *next_process = processes[ next_sch_pid ];\n\t\n\tcurr_sch_pid = next_sch_pid;\n\tnext_sch_pid++;\n\tnext_sch_pid = next_sch_pid % processes_count;\n\t\n\treturn next_process;\n}\n\nvoid scheduler( int eip, int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax )\n{\n\tprocess_t *curr_process;\n\t\n\tprint( \" EAX = \" );\n\tprinti( eax );\n\n\tcurr_process = processes[ curr_sch_pid ];\n\tnext_process = get_next_process();\n\t\t\n\t// Copy Current Process Context to The Memory\n\tif ( curr_process->state == RUNNING )\n\t{\n\t\tcurr_process->context.eax = eax;\n\t\tcurr_process->context.ecx = ecx;\n\t\tcurr_process->context.edx = edx;\n\t\tcurr_process->context.ebx = ebx;\n\t\tcurr_process->context.esp = esp;\n\t\tcurr_process->context.ebp = ebp;\n\t\tcurr_process->context.esi = esi;\n\t\tcurr_process->context.edi = edi;\n\t\tcurr_process->context.eip = eip;\n\t}\n\t\n\tcurr_process->state = READY;\n\t\n\t// ... //\n\t\n\t// Copy Next Process Context to The Processor\n\t// TODO: In Memory-Management Version. Copy ESP and EBP\n\tasm( \"\tmov %0, %%eax;\t\\\n\t\t\tmov %0, %%ecx;\t\\\n\t\t\tmov %0, %%edx;\t\\\n\t\t\tmov %0, %%ebx;\t\\\n\t\t\tmov %0, %%esi;\t\\\n\t\t\tmov %0, %%edi;\" \n\t\t\t: : \"r\" ( next_process->context.eax ), \"r\" ( next_process->context.ecx ), \"r\" ( next_process->context.edx ), \"r\" ( next_process->context.ebx ),\n\t\t\t\t\"r\" ( next_process->context.esi ), \"r\" ( next_process->context.edi ) );\n\t\n\tnext_process->state = RUNNING;\n}\n\nvoid run_next_process()\n{\n\t// No code should reside here at all. Otherwise,\n\t// we will not be sure that the context of the process\n\t// to run will be correct.\n\t\n\tasm( \"\tsti;\t\t\t\\\n\t \t\tjmp *%0\" : : \"r\" ( next_process->context.eip ) );\n}\n"
  },
  {
    "path": "src/scheduler.h",
    "content": "#include \"process.h\"\n\nint next_sch_pid, curr_sch_pid;\n\nprocess_t *next_process;\n\nvoid scheduler_init();\nprocess_t *get_next_process();\nvoid scheduler( int, int, int, int, int, int, int, int, int );\nvoid run_next_process();\n"
  },
  {
    "path": "src/screen.c",
    "content": "#include \"screen.h\"\n\nvoid screen_init()\n{\n\t// VGA Text Mode = 0xB8000\n\t// VGA Graphics Mode = 0xA0000\n\tvideo = 0xB8000;\n\tnextTextPos = 0;\n\tcurrLine = 0;\n}\n\nvoid print( char *str )\n{\n\tint currCharLocationInVidMem, currColorLocationInVidMem;\n\t\n\twhile ( *str != '\\0' )\n\t{\n\t\tcurrCharLocationInVidMem = nextTextPos * 2;\n\t\tcurrColorLocationInVidMem = currCharLocationInVidMem + 1;\n\t\t\n\t\tvideo[ currCharLocationInVidMem ] = *str;\n\t\tvideo[ currColorLocationInVidMem ] = 15;\n\t\t\n\t\tnextTextPos++;\n\t\t\n\t\tstr++;\n\t}\n}\n\nvoid println()\n{\n\tif ( currLine > 23 )\n\t{\n\t\tcls();\n\t\treturn;\n\t}\n\t\n\tnextTextPos = ++currLine * 80;\n}\n\nvoid printi( int number )\n{\n\tchar* digitToStr[] = { \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\" };\n\t\n\tif ( number >= 0 && number <= 9 )\n\t{\n\t\tprint( digitToStr[ number ] );\n\t\treturn;\n\t}\n\telse\n\t{\n\t\tint remaining = number % 10;\n\t\tnumber = number / 10;\n\t\t\n\t\tprinti( number );\n\t\tprinti( remaining );\n\t}\n}\n\nvoid cls()\n{\n\tfor ( int currPos = 0; currPos < 3999; currPos = currPos + 2 )\n\t{\n\t\tvideo[ currPos ] = 0;\n\t\tvideo[ currPos + 1 ] = 0;\n\t}\n\t\n\tnextTextPos = 0;\n\tcurrLine = 0;\n\t\n}\n\n"
  },
  {
    "path": "src/screen.h",
    "content": "volatile unsigned char *video;\n\nint nextTextPos;\nint currLine;\n\nvoid screen_init();\nvoid print( char * );\nvoid println();\nvoid printi( int );\nvoid cls();\n"
  },
  {
    "path": "src/simple_kernel.asm",
    "content": "start:\n\tmov ax, cs\n\tmov ds, ax\n\t\n\t; --- ;\n\t\n\tmov si, hello_string\n\tcall print_string\n\t\n\tjmp $\n\nprint_string:\n\tmov ah, 0Eh\n\nprint_char:\n\tlodsb\n\t\n\tcmp al, 0\n\tje done\n\t\n\tint 10h\n\t\n\tjmp print_char\n\ndone:\n\tret\n\t\nhello_string db 'Hello World!, From Simple Assembly 539kernel!', 0\n"
  },
  {
    "path": "src/starter.asm",
    "content": "bits 16\nextern kernel_main\nextern interrupt_handler\nextern scheduler\nextern run_next_process\nextern page_directory\n\nglobal load_page_directory\nglobal enable_paging\n\nglobal dev_write\nglobal dev_write_word\nglobal dev_read\n\nstart:\n\tmov ax, cs\n\tmov ds, ax\n\t\t\n\t; --- ;\n\t\n\tcall load_gdt\n\tcall init_video_mode\n\tcall enter_protected_mode\n\tcall setup_interrupts\n\tcall load_task_register\n\t\n\t; --- ;\n\t\n\tcall 08h:start_kernel\n\t\nload_gdt:\n\tcli\n\tlgdt [gdtr - start]\n\t\n\tret\n\t\nsetup_interrupts:\n\tcall remap_pic\n\tcall load_idt\n\t\n\tret\n\t\ninit_video_mode:\n\t;; Set Video Mode\n\tmov ah, 0h\n\tmov al, 03h ; 03h For Text Mode. 13h For Graphics Mode.\n\tint 10h\n\t\n\t;; Disable Text Cursor\n\tmov ah, 01h\n\tmov cx, 2000h\n\tint 10h\n\t\n\tret\n\nenter_protected_mode:\n\tmov eax, cr0\n\tor eax, 1\n\tmov cr0, eax\n\t\n\tret\n\t\nremap_pic:\n\tmov al, 11h\n\t\n\tsend_init_cmd_to_pic_master: \t\n\t\tout 0x20, al\n\t\t\n\tsend_init_cmd_to_pic_slave: \t\n\t\tout 0xa0, al\n\t\t\n\t; ... ;\n\t\n\tmake_irq_starts_from_intr_32_in_pic_master:\t\t\n\t\tmov al, 32d\n\t\tout 0x21, al\n\t\n\tmake_irq_starts_from_intr_40_in_pic_slave:\n\t\tmov al, 40d\n\t\tout 0xa1, al \n\t\n\t; ... ;\n\t\n\ttell_pic_master_where_pic_slave_is_connected:\n\t\tmov al, 04h\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_where_pic_master_is_connected:\n\t\tmov al, 02h\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 01h\n\t\n\ttell_pic_master_the_arch_is_x86:\n\t\tout 0x21, al\n\t\n\ttell_pic_slave_the_arch_is_x86:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tmov al, 0h\n\t\n\tmake_pic_master_enables_all_irqs:\n\t\tout 0x21, al\n\t\n\tmake_pic_slave_enables_all_irqs:\n\t\tout 0xa1, al\n\t\n\t; ... ;\n\t\n\tret\n\nload_idt:\n\tlidt [idtr - start]\n\tret\n\t\nload_task_register:\n\tmov ax, 40d\n\tltr ax\n\t\n\tret\n\t\nbits 32\nload_page_directory:\n\tmov eax, [page_directory]\n\tmov cr3, eax\n\t\n\tret\n\t\nenable_paging:\n\tmov eax, cr0\n\tor eax, 80000000h\n\tmov cr0, eax\n\t\n\tret\n\t\n; --- ;\n\n; dev_write( int port, int cmd );\ndev_write:\n\tpush edx\n\tpush eax\n\t\n\txor edx, edx\n\txor eax, eax\n\t\n\tmov dx, [esp + 12]\n\tmov al, [esp + 16]\n\t\n\tout dx, al \n\t\n\tpop eax\n\tpop edx\n\t\n\tret\n\t\ndev_write_word:\n\tpush edx\n\tpush eax\n\t\n\txor edx, edx\n\txor eax, eax\n\t\n\tmov dx, [esp + 12]\n\tmov ax, [esp + 16]\n\t\n\tout dx, ax \n\t\n\tpop eax\n\tpop edx\n\t\n\tret\n\n; dev_read( int port );\ndev_read:\n\tpush edx\n\t\n\txor edx, edx\n\txor eax, eax\n\t\n\tmov dx, [esp + 8]\n\t\n\tin ax, dx\n\t\n\t;jmp $\n\t\n\tpop edx\n\t\n\tret\n\nstart_kernel:\n\tmov eax, 10h\n\tmov ds, eax\n\tmov ss, eax\n\tmov es, eax\n\t\n\tmov eax, 0h\n\tmov fs, eax\n\tmov gs, eax\n\t\n\t;sti ; TODO: I think we need to enable it. Does the multitasking work? 13 Nov 2022. Check if we enabled interrupts elsewhere?\n\t\n\tcall kernel_main\n\t\n%include \"gdt.asm\"\n%include \"idt.asm\"\n\ntss:\n\tdd 0\n"
  },
  {
    "path": "src/str.c",
    "content": "#include \"str.h\"\n\nvoid strcpy( char *dest, char *src )\n{\n\tint idx = 0;\n\t\n\twhile ( *src != '\\0' )\n\t{\n\t\tdest[ idx ] = *src;\n\t\t\n\t\tsrc++;\n\t\tidx++;\n\t}\n}\n\nint strcmp( char *str1, char *str2 )\n{\n\twhile ( *str1 != '\\0' )\n\t{\n\t\tif ( *str1 != *str2 )\n\t\t\treturn 0;\n\t\t\n\t\tstr1++;\n\t\tstr2++;\n\t}\n\t\n\tif ( *str2 != '\\0' )\n\t\treturn 0;\n\t\n\treturn 1;\n}\n"
  },
  {
    "path": "src/str.h",
    "content": "void strcpy( char *, char * );\nint strcmp( char *, char * );\n"
  }
]