├── COMMENTS_sector1 ├── README.md ├── compile.sh └── sector1.bin /COMMENTS_sector1: -------------------------------------------------------------------------------- 1 | sector1 (boot sector) will be loaded into memory 7C00 by BIOS 2 | Running in 16-bit x86 Real Mode. 3 | 4 | 5 | 0500: RAM Variables (uninitialized on start) 6 | 7 | 0500 Input buffer pointer offset relative to 0501 8 | 0501..05FF Input buffer 9 | 10 | 11 | 7C00 to 7D4F: Main code 12 | 13 | Startup 14 | 15 | 7C00 MOVDX word 7DBD 16 | 7C03 CALL word +14A to 7D50 (Message) 17 | 7C06 CALL word +87 to 7C90 (Init) 18 | 7C09 CALL word +164 to 7D70 (Prompt) 19 | 20 | 7C0C..7C0F NOP 21 | 22 | Scan and print; typing. Also calls 7C30 to handle each character. 23 | 24 | 7C10 XOR (reg to rm) byte 11AHAH 25 | 7C12 INT byte 16 26 | 7C14 CALL word +19 to 7C30 27 | 7C17 NOP 28 | 7C18 CALL word +165 to 7D80 29 | 7C1B NOP 30 | 7C1C JMP byte -E to 7C10 31 | 32 | Halt the system. 33 | 34 | 7C20 MOVDX word 7DD2 35 | 7C23 CALL word +12A to 7D50 36 | 7C26 NOP 37 | 7C27 NOP 38 | 7C28 CLI 39 | 7C29 HLT 40 | 41 | Handle keyboard character. 42 | 43 | 7C30 CMPAL byte 11 (Ctrl-Q ascii) 44 | 7C32 JZ byte -14 to 7C20 45 | 7C34 CMPAL byte D (return ascii) 46 | 7C36 JZ byte +F to 7C47 47 | 7C38 CMPAL byte 8 (backspace ascii) 48 | 7C3A JZ byte +26 to 7C62 49 | 50 | Handle normal character. 51 | 52 | 7C3C..7C3F NOP 53 | 54 | 7C40 CALL word +25 to 7C68 55 | 56 | 7C43 NOP 57 | 7C44 NOP 58 | 59 | 7C45 RET 60 | 7C46 NOP 61 | 62 | Handle return. 63 | 64 | 7C47 MOVDX word 7DCD 65 | 7C4A CALL +103 word to 7D50 66 | 67 | 7C4D..7C51 NOP 68 | 69 | 7C52 MOV (immediate8) byte 00000110 word 500 byte 0 (Reset input buffer pointer) 70 | 7C57 NOP 71 | 7C58 NOP 72 | 7C59 CALL word +114 to 7D70 73 | 7C5C ADD byte 11000SP word 2 74 | 7C60 JMP byte -52 to 7C10 (don't print, return to read immediately) 75 | 76 | Bounce Hub: Handle Characters -- Handle Backspace 77 | 78 | 7C62 JMP byte +62 to 7CC6 ( --> Jump over into function) 79 | 7C64 JMP byte -21 to 7C45 ( <-- Print but don't handle) 80 | 7C66 NOP 81 | 7C67 NOP 82 | 83 | Handle putting characters into input buffer. Check overflow. 84 | 85 | 7C68 MOV (r/m to reg) byte 00CL110 word 7DE7 86 | 7C6C XOR (r/m to reg) byte 11BXBX 87 | 7C6E MOV (r/m to reg) byte 00BL110 word 500 88 | 7C72 CMP (reg first) byte 11BLCL 89 | 7C74 JA byte +E to 7C84 90 | 91 | Put into buffer 92 | 93 | 7C76 MOV (reg to r/m) byte 10AL111 word +501 ([BX + 501]) 94 | 7C7A NOP 95 | 7C7B INC byte 00000110 word 500 96 | 7C7F NOP 97 | 7C80 NOP 98 | 7C81 RET 99 | 100 | Handle rejecting overflow. 101 | 102 | 7C84 INCCL 103 | 7C85 NOP 104 | 7C86 MOV (reg to r/m) byte 00CL110 word 500 (offset = max + 1 in case it was more. it is max + 1 because max is writable, max + 1 is not. offset represents the next writing position. by setting to max it means that you can overwrite the last one after overflow, which is unintended. by max + 1, it means that you can not [over]write anything until you go back, which is intended.) 105 | 7C8A ADD byte 11000SP word 4 106 | 7C8E JMP byte -80 to 7C10 (don't print, return to read immediately) 107 | 108 | Initialize system 109 | 110 | 7C90 MOVDX word 7DE8 111 | 7C93 CALL word +BA to 7D50 112 | 7C96 MOVDX word 7DF2 113 | 7C99 CALL word +B4 to 7D50 114 | 7C9C MOV (immediate8) byte 00000110 word 500 byte 0 (Reset input buffer pointer) 115 | 116 | 7CA1..7CAC NOP 117 | 118 | 7CAD MOVDX word 7DE8 119 | 7CB0 CALL word +9D to 7D50 120 | 7CB3 MOVDX word 7DE0 121 | 7CB6 CALL word +97 to 7D50 122 | 7CB9 MOVDX word 7DCD 123 | 7CBC CALL word +91 to 7D50 124 | 7CBF MOVALMEM word 7DCE 125 | 7CC2 CALL word +BB to 7D80 126 | 7CC5 RET 127 | 128 | Handle backspace 129 | 130 | 7CC6 CMP (immediate8) byte 00000110 word 500 byte 0 131 | 7CCB JZ byte -6D to 7C60 (don't print, return to read immediately) 132 | 7CCD DEC byte 00001110 word 500 133 | 7CD1 JMP byte -6F to 7C64 (print but don't handle as normal 134 | character -- don't input into buffer) 135 | 136 | 137 | 7D40 to 7D4F: Procedures far-call vector table code 138 | 139 | 7D40 CALL word +D to 7D50 140 | 7D43 RETF 141 | 7D44 CALL word +29 to 7D70 142 | 7D47 RETF 143 | 7D48 CALL word to 7D80 144 | 7D4A RETF 145 | 146 | 147 | 7D50 to 7DBC: Procedures code 148 | 149 | 7D50 to 7D6F: String print code 150 | 151 | In DX: String address, null-terminated. 152 | Out SI: Length of string, excluding null-term character. 153 | 154 | 7D50 XOR (r/m to reg) byte 11SISI 155 | 7D52 MOV (r/m to reg) byte 11BXDX 156 | 7D54 MOV (r/m to reg) byte 00AX000 ([BX + SI]) 157 | 7D56 CMPAL byte 0 158 | 7D58 JZ byte +9 to 7D63 159 | 7D5A CALL word +23 to 7D80 160 | 7D5D NOP 161 | 7D5E NOP 162 | 7D5F NOP 163 | 7D60 INCSI 164 | 7D61 JMP byte -11 to 7D52 165 | 7D63 RET 166 | 167 | 7D70 to 7D7F: Print prompt code 168 | 169 | Out DX: Prompt string address. 170 | 171 | 7D70 MOVDX word 7DE4 172 | 7D73 CALL word -26 to 7D50 173 | 7D76 NOP 174 | 7D77 NOP 175 | 7D78 RET 176 | 177 | 7D80 to 7D8F: Print character with default options 178 | 179 | In AL: Character ASCII 180 | 181 | 7D80 XOR (r/m to reg) byte 11BXBX 182 | 183 | 7D82 to 7D8F: Print character with options 184 | 185 | In BL: next 186 | In BH: Refer to int-10h options E. 187 | 188 | 7D82 MOVAH byte E 189 | 7D84 INT byte 10 190 | 7D86 RET 191 | 192 | 193 | 7DBD to 7DFD: Data 194 | 195 | 7DBD 7, "TestOS loaded.", A 196 | 7DCD D (carriagereturn@7DCD), A (linefeed@7DCE), 0 197 | 7DD2 D, A, A, "System halt" 198 | 7DE0 "ed.", 0 199 | 7DE4 "$ ", 0 (Prompt) 200 | 7DE7 byte FE (Input buffer max pointer offset, must not be FF) 201 | 7DE8 "Initializ", 0 202 | 7DF2 "ing...", D, A, 0 203 | 204 | 205 | 7DFE to 7DFF: Bootable magic numbers data 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Test OS 2 | Test OS is a very barebone operating system that it loaded by the BIOS into 0x7c00 and from there, executes assembly instructions immediately. No EFI, no config, no boot folders. It's like programming for the C64, but for modern computers! Works on most x86 IBM-compatible PCs. 3 | 4 | Written fully in hex, by a hex editor only. 5 | 6 | Based on tutorial: http://www.brokenthorn.com/Resources/OSDev3.html 7 | 8 | ## Preparing the boot disk 9 | Note: If you're a Windows user, you'll need to install Cygwin to use the script, do this step manually, or use another program that does something like this. 10 | 11 | ### Using the script 12 | cd test-os 13 | ./compile.sh 14 | 15 | You'll find a file named "boot.img" in the test-os folder. This is the 1.44MB floppy disk boot image. 16 | 17 | ### Manually 18 | First of all, generate a 1.44MB floppy disk image. The contents of it don't matter. After that, copy the 512-byte sector1.bin into the first 512 bytes of the floppy disk image (i.e. the first sector). The result is a floppy disk boot image. 19 | 20 | ## Booting 21 | 22 | ### On VirtualBox 23 | 1. Create a new VM 24 | 2. Give any name. The OS should be Other/Other, 32-bit. (Though 64-bit is fine as well) 25 | 3. Give as much memory as you want to it; it's just going to use 257 bytes anyway. 26 | 4. Create without a hard disk. 27 | 5. In Settings->Storage of the VM, add a Floppy Controller and choose "boot.img" or your manually-made floppy disk boot image as its disk. 28 | 6. Run the VM. 29 | 30 | ### On a real PC 31 | 1. Image the floppy disk boot image onto a floppy disk. 32 | 2. Insert the floppy disk into the PC. 33 | 3. Boot your PC and select the option to boot from floppy disk. Contact your manual for details. 34 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 4 | echo "Deleting boot.img if any to ensure complete overwrite..." 5 | rm boot.img 6 | echo "OK" 7 | echo 8 | echo "Generating 1.44MB boot.img blank floppy..." 9 | dd if=/dev/zero of=boot.img bs=1k count=1440 10 | echo "OK" 11 | echo 12 | echo "Copying sector1.bin into sector 1 of boot.img..." 13 | dd if=sector1.bin of=boot.img bs=512 conv=notrunc 14 | echo "OK" 15 | 16 | echo 17 | echo "Done. 1.44MB floppy boot.img is located in '.'." 18 | echo "You can boot this image in any PC x86 emulator," 19 | echo 20 | -------------------------------------------------------------------------------- /sector1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/limdingwen/test-os/294a9041892532c82ac232b5627548338b725692/sector1.bin --------------------------------------------------------------------------------