https://github.com/akkartik/mu/blob/main/boot.subx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 == code
26
27
28
29
30
31
32
33
34
35 fa/disable-interrupts
36
37
38 b8/copy-to-ax 0/imm16
39 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
40 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
41 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
42 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
43
44
45
46
47
48 b8/copy-to-ax 0x7000/imm16
49 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
50 bc/copy-to-esp 0/imm16
51
52
53
54 {
55 e4/read-port-into-al 0x64/imm8
56 a8/test-bits-in-al 0x02/imm8
57 75/jump-if-!zero loop/disp8
58 b0/copy-to-al 0xd1/imm8
59 e6/write-al-into-port 0x64/imm8
60 }
61 {
62 e4/read-port-into-al 0x64/imm8
63 a8/test-bits-in-al 0x02/imm8
64 75/jump-if-!zero loop/disp8
65 b0/copy-to-al 0xdf/imm8
66 e6/write-al-into-port 0x64/imm8
67 }
68
69
70 b4/copy-to-ah 2/imm8/read-drive
71
72 b5/copy-to-ch 0/imm8/cylinder
73 b6/copy-to-dh 0/imm8/head
74 b1/copy-to-cl 2/imm8/sector
75 b0/copy-to-al 0x7d/imm8/num-sectors
76
77 bb/copy-to-bx 0/imm16
78 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
79 bb/copy-to-bx 0x7e00/imm16
80 cd/syscall 0x13/imm8/bios-disk-services
81 0f 82/jump-if-carry disk_error/disp16
82
83
84 b4/copy-to-ah 2/imm8/read-drive
85
86 b5/copy-to-ch 0/imm8/cylinder
87 b6/copy-to-dh 2/imm8/head
88 b1/copy-to-cl 1/imm8/sector
89 b0/copy-to-al 0x7e/imm8/num-sectors
90
91 bb/copy-to-bx 0x1780/imm16
92 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
93 bb/copy-to-bx 0/imm16
94 cd/syscall 0x13/imm8/bios-disk-services
95 0f 82/jump-if-carry disk_error/disp16
96
97
98 b4/copy-to-ah 2/imm8/read-drive
99
100 b5/copy-to-ch 0/imm8/cylinder
101 b6/copy-to-dh 4/imm8/head
102 b1/copy-to-cl 1/imm8/sector
103 b0/copy-to-al 0x7e/imm8/num-sectors
104
105 bb/copy-to-bx 0x2740/imm16
106 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
107 bb/copy-to-bx 0/imm16
108 cd/syscall 0x13/imm8/bios-disk-services
109 0f 82/jump-if-carry disk_error/disp16
110
111
112 b4/copy-to-ah 2/imm8/read-drive
113
114 b5/copy-to-ch 0/imm8/cylinder
115 b6/copy-to-dh 6/imm8/head
116 b1/copy-to-cl 1/imm8/sector
117 b0/copy-to-al 0x7e/imm8/num-sectors
118
119 bb/copy-to-bx 0x3700/imm16
120 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
121 bb/copy-to-bx 0/imm16
122 cd/syscall 0x13/imm8/bios-disk-services
123 0f 82/jump-if-carry disk_error/disp16
124
125
126 bb/copy-to-bx 0/imm16
127 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
128
129
130 b4/copy-to-ah 0x4f/imm8
131 b0/copy-to-al 2/imm8
132 bb/copy-to-bx 0x4105/imm16
133
134
135
136 cd/syscall 0x10/imm8/bios-video-services
137
138
139
140 b4/copy-to-ah 0x4f/imm8
141 b0/copy-to-al 1/imm8
142 b9/copy-to-cx 0x0105/imm16
143 bf/copy-to-di Video-mode-info/imm16
144 cd/syscall 0x10/imm8/bios-video-services
145
146
147
148
149
150
151 0f 01 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7ce0/disp16/gdt_descriptor
152
153 0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
154 66 83 1/subop/or 3/mod/direct 0/rm32/eax 1/imm8
155 0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
156
157
158
159 ea/jump-far-absolute 0x00087d00/disp32
160
161 disk_error:
162
163
164 bb/copy-to-bx 0xb800/imm16
165 8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
166 b0/copy-to-al 0x44/imm8/D
167 b4/copy-to-ah 0x0f/imm8/white-on-black
168 bb/copy-to-bx 0/imm16
169 89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax
170
171 {
172 eb/jump loop/disp8
173 }
174
175
176 == data 0x7ce0
177 gdt_descriptor:
178 0x17/imm16
179 gdt_start/imm32/start
180
181 gdt_start:
182
183 00 00 00 00 00 00 00 00
184
185 ff ff
186 00 00 00
187 9a
188
189 cf
190
191 00
192
193 ff ff
194 00 00 00
195 92
196
197 cf
198 00
199
200
201
202
203 == code 0x7d00
204 initialize_32bit_mode:
205 66 b8/copy-to-ax 0x10/imm16
206 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
207 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
208 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
209 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
210 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
211
212 bc/copy-to-esp 0x02000000/imm32
213
214
215
216
217
218 0f 01 3/subop/lidt 0/mod/indirect 5/rm32/use-disp32 0x7e00/disp32/idt_descriptor
219
220
221
222
223
224
225
226
227
228
229
230 b0/copy-to-al 0xfc/imm8
231 e6/write-al-into-port 0x21/imm8
232
233 fb/enable-interrupts
234
235 (initialize-mouse)
236
237
238 db/floating-point-coprocessor e3/initialize
239
240 0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
241
242 0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
243
244 0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
245
246 e9/jump Entry/disp32
247
248 == boot-sector-marker 0x7dfe
249
250 55 aa
251
252
253
254 == data 0x7e00
255 idt_descriptor:
256 ff 03
257 idt_start/imm32/start
258
259 +-- 55 lines: # interrupt descriptor table ----------------------------------------------------------------------------------------------------------------------------------------------
314
315 == code
316
317 null-interrupt-handler:
318
319
320
321 fa/disable-interrupts
322 60/push-all-registers
323 9c/push-flags
324
325 b0/copy-to-al 0x20/imm8
326 e6/write-al-into-port 0x20/imm8
327 31/xor %eax 0/r32/eax
328 $null-interrupt-handler:epilogue:
329
330 9d/pop-flags
331 61/pop-all-registers
332 fb/enable-interrupts
333 cf/return-from-interrupt
334
335 timer-interrupt-handler:
336
337
338
339 fa/disable-interrupts
340 60/push-all-registers
341 9c/push-flags
342
343 b0/copy-to-al 0x20/imm8
344 e6/write-al-into-port 0x20/imm8
345 31/xor %eax 0/r32/eax
346 $timer-interrupt-handler:epilogue:
347
348 9d/pop-flags
349 61/pop-all-registers
350 fb/enable-interrupts
351 cf/return-from-interrupt
352
353 keyboard-interrupt-handler:
354
355 fa/disable-interrupts
356 60/push-all-registers
357 9c/push-flags
358
359 b0/copy-to-al 0x20/imm8
360 e6/write-al-into-port 0x20/imm8
361 31/xor %eax 0/r32/eax
362
363 e4/read-port-into-al 0x64/imm8
364 a8/test-bits-in-al 0x01/imm8
365 0f 84/jump-if-not-set $keyboard-interrupt-handler:epilogue/disp32
366
367
368 31/xor %ecx 1/r32/ecx
369 8a/byte-> *Keyboard-buffer:write 1/r32/cl
370 81 0/subop/add %ecx Keyboard-buffer:data/imm32
371
372 8a/byte-> *ecx 0/r32/al
373
374 3c/compare-al-and 0/imm8
375 0f 85/jump-if-!= $keyboard-interrupt-handler:epilogue/disp32
376
377 e4/read-port-into-al 0x60/imm8
378
379
380 {
381 3c/compare-al-and 0xaa/imm8
382 75/jump-if-!= break/disp8
383
384 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
385 }
386
387 {
388 3c/compare-al-and 0xb6/imm8
389 75/jump-if-!= break/disp8
390
391 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
392 }
393
394 {
395 3c/compare-al-and 0x9d/imm8
396 75/jump-if-!= break/disp8
397
398 c7 0/subop/copy *Keyboard-ctrl-pressed? 0/imm32
399 }
400
401 50/push-eax
402 24/and-al-with 0x80/imm8
403 3c/compare-al-and 0/imm8
404 58/pop-to-eax
405 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
406
407
408 {
409 3c/compare-al-and 0x2a/imm8
410 75/jump-if-!= break/disp8
411
412 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
413
414 eb/jump $keyboard-interrupt-handler:epilogue/disp8
415 }
416
417 {
418 3c/compare-al-and 0x36/imm8
419 75/jump-if-!= break/disp8
420
421 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
422
423 eb/jump $keyboard-interrupt-handler:epilogue/disp8
424 }
425
426 {
427 3c/compare-al-and 0x1d/imm8
428 75/jump-if-!= break/disp8
429
430 c7 0/subop/copy *Keyboard-ctrl-pressed? 1/imm32
431
432 eb/jump $keyboard-interrupt-handler:epilogue/disp8
433 }
434
435
436 {
437 81 7/subop/compare *Keyboard-shift-pressed? 0/imm32
438 74/jump-if-= break/disp8
439
440 05/add-to-eax Keyboard-shift-map/imm32
441 8a/byte-> *eax 0/r32/al
442 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
443 }
444
445 {
446 81 7/subop/compare *Keyboard-ctrl-pressed? 0/imm32
447 74/jump-if-= break/disp8
448 05/add-to-eax Keyboard-ctrl-map/imm32
449 8a/byte-> *eax 0/r32/al
450 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
451 }
452
453 05/add-to-eax Keyboard-normal-map/imm32
454 8a/byte-> *eax 0/r32/al
455 $keyboard-interrupt-handler:select-map-done:
456
457 {
458 3c/compare-al-and 0/imm8
459 74/jump-if-= break/disp8
460
461 88/<- *ecx 0/r32/al
462
463 fe/increment-byte *Keyboard-buffer:write
464
465 80 4/subop/and-byte *Keyboard-buffer:write 0x0f/imm8
466 }
467 $keyboard-interrupt-handler:epilogue:
468
469 9d/pop-flags
470 61/pop-all-registers
471 fb/enable-interrupts
472 cf/return-from-interrupt
473
474 == data
475 Keyboard-shift-pressed?:
476 0/imm32
477
478 Keyboard-ctrl-pressed?:
479 0/imm32
480
481
482 Keyboard-buffer:write:
483 0/imm32
484 Keyboard-buffer:read:
485 0/imm32
486 Keyboard-buffer:data:
487 00 00 00 00
488 00 00 00 00
489 00 00 00 00
490 00 00 00 00
491
492 +-- 95 lines: # Keyboard maps for translating keys to ASCII -----------------------------------------------------------------------------------------------------------------------------
587
588 Video-mode-info:
589 +-- 53 lines: # video mode info ---------------------------------------------------------------------------------------------------------------------------------------------------------
642
643 Font:
644 +--236 lines: # Bitmaps for some ASCII characters (soon Unicode) ------------------------------------------------------------------------------------------------------------------------
880
881
882
883
884
885
886
887
888
889
890 == data
891
892
893
894 Primary-bus-primary-drive:
895
896 0x1f7/imm32
897
898 0x1f7/imm32
899
900 0x3f6/imm32
901
902 0x1f1/imm32
903
904 0x1f6/imm32
905
906 0x1f2/imm32
907
908 0x1f3/imm32
909
910 0x1f4/imm32
911
912 0x1f5/imm32
913
914 0x1f0/imm32
915
916 0xe0/imm32
917
918
919
920 Primary-bus-secondary-drive:
921
922 0x1f7/imm32
923
924 0x1f7/imm32
925
926 0x3f6/imm32
927
928 0x1f1/imm32
929
930 0x1f6/imm32
931
932 0x1f2/imm32
933
934 0x1f3/imm32
935
936 0x1f4/imm32
937
938 0x1f5/imm32
939
940 0x1f0/imm32
941
942 0xf0/imm32
943
944 == code
945
946 load-sectors:
947
948 55/push-ebp
949 89/<- %ebp 4/r32/esp
950
951 50/push-eax
952 51/push-ecx
953 52/push-edx
954
955 (drive-exists? *(ebp+8))
956 3d/compare-eax-and 0/imm32/false
957 0f 84/jump-if-= $load-sectors:end/disp32
958
959 (ata-drive-select *(ebp+8) *(ebp+0xc))
960 (clear-ata-error *(ebp+8))
961 (ata-sector-count *(ebp+8) *(ebp+0x10))
962 (ata-lba *(ebp+8) *(ebp+0xc))
963 (ata-command *(ebp+8) 0x20)
964
965 {
966
967
968
969 (while-ata-busy *(ebp+8))
970 (until-ata-data-available *(ebp+8))
971
972
973 8b/-> *(ebp+8) 0/r32/eax
974 8b/-> *(eax+0x24) 2/r32/edx
975
976 31/xor %eax 0/r32/eax
977 b9/copy-to-ecx 0x200/imm32
978 {
979 81 7/subop/compare %ecx 0/imm32
980 74/jump-if-= break/disp8
981 66 ed/read-port-dx-into-ax
982
983 (append-byte *(ebp+0x14) %eax)
984 49/decrement-ecx
985 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
986 (append-byte *(ebp+0x14) %eax)
987 49/decrement-ecx
988 eb/jump loop/disp8
989 }
990
991 ff 1/subop/decrement *(ebp+0x10)
992
993 81 7/subop/compare *(ebp+0x10) 0/imm32
994 7e/jump-if-<= break/disp8
995 (wait-400ns *(ebp+8))
996
997 e9/jump loop/disp32
998 }
999 $load-sectors:end:
1000
1001 5a/pop-to-edx
1002 59/pop-to-ecx
1003 58/pop-to-eax
1004
1005 89/<- %esp 5/r32/ebp
1006 5d/pop-to-ebp
1007 c3/return
1008
1009 store-sectors:
1010
1011 55/push-ebp
1012 89/<- %ebp 4/r32/esp
1013
1014 50/push-eax
1015 51/push-ecx
1016 52/push-edx
1017 53/push-ebx
1018
1019 (drive-exists? *(ebp+8))
1020 3d/compare-eax-and 0/imm32/false
1021 0f 84/jump-if-= $store-sectors:end/disp32
1022
1023 (ata-drive-select *(ebp+8) *(ebp+0xc))
1024 (clear-ata-error *(ebp+8))
1025 (ata-sector-count *(ebp+8) *(ebp+0x10))
1026 (ata-lba *(ebp+8) *(ebp+0xc))
1027 (ata-command *(ebp+8) 0x30)
1028
1029
1030
1031 {
1032
1033 (while-ata-busy *(ebp+8))
1034 (until-ata-ready-for-data *(ebp+8))
1035
1036 8b/-> *(ebp+8) 0/r32/eax
1037 8b/-> *(eax+0x24) 2/r32/edx
1038
1039 b9/copy-to-ecx 0x200/imm32
1040
1041
1042 bb/copy-to-ebx 0xffff/imm32
1043
1044 $store-sectors:store-sector:
1045 {
1046 81 7/subop/compare %ecx 0/imm32
1047 74/jump-if-= break/disp8
1048
1049 (stream-empty? *(ebp+0x14))
1050 3d/compare-eax-and 0/imm32/false
1051 75/jump-if-!= break/disp8
1052
1053 (read-byte *(ebp+0x14))
1054
1055 81 7/subop/compare %ebx 0xff/imm32
1056 {
1057 7e/jump-if-<= break/disp8
1058 89/<- %ebx 0/r32/eax
1059 eb/jump $store-sectors:store-sector/disp8
1060 }
1061
1062 c1/shift 4/subop/left %eax 8/imm8
1063 09/or %eax 3/r32/ebx
1064 66 ef/write-ax-into-port-dx
1065 49/decrement-ecx
1066 49/decrement-ecx
1067
1068 bb/copy-to-ebx 0xffff/imm32
1069 eb/jump loop/disp8
1070 }
1071
1072
1073 81 7/subop/compare %ebx 0xff/imm32
1074 {
1075 7f/jump-if-> break/disp8
1076 89/<- %eax 3/r32/ebx
1077 66 ef/write-ax-into-port-dx
1078 49/decrement-ecx
1079 49/decrement-ecx
1080 }
1081
1082
1083 31/xor %eax 0/r32/eax
1084 {
1085 81 7/subop/compare %ecx 0/imm32
1086 74/jump-if-= break/disp8
1087 66 ef/write-ax-into-port-dx
1088 49/decrement-ecx
1089 49/decrement-ecx
1090 eb/jump loop/disp8
1091 }
1092
1093
1094 ff 1/subop/decrement *(ebp+0x10)
1095 81 7/subop/compare *(ebp+0x10) 0/imm32
1096 7e/jump-if-<= break/disp8
1097
1098 (wait-400ns *(ebp+8))
1099
1100 e9/jump loop/disp32
1101 }
1102
1103 (flush-ata-cache *(ebp+8))
1104
1105 $store-sectors:end:
1106
1107 5b/pop-to-ebx
1108 5a/pop-to-edx
1109 59/pop-to-ecx
1110 58/pop-to-eax
1111
1112 89/<- %esp 5/r32/ebp
1113 5d/pop-to-ebp
1114 c3/return
1115
1116 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415 read-mouse-event:
1416
1417 55/push-ebp
1418 89/<- %ebp 4/r32/esp
1419
1420 52/push-edx
1421 53/push-ebx
1422
1423 b8/copy-to-eax 0/imm32
1424 b9/copy-to-ecx 0/imm32
1425 (any-mouse-event?)
1426 3d/compare-eax-and 0/imm32/false
1427 74/jump-if-= $read-mouse-event:end/disp8
1428
1429 31/xor %eax 0/r32/eax
1430 e4/read-port-into-al 0x60/imm8
1431 89/<- %edx 0/r32/eax
1432 (wait-for-mouse-event)
1433
1434 31/xor %eax 0/r32/eax
1435 e4/read-port-into-al 0x60/imm8
1436 89/<- %ebx 0/r32/eax
1437 (wait-for-mouse-event)
1438
1439 31/xor %eax 0/r32/eax
1440 e4/read-port-into-al 0x60/imm8
1441 89/<- %ecx 0/r32/eax
1442
1443 89/<- %eax 3/r32/ebx
1444
1445 {
1446 f6 0/subop/test-bits %dl 0x10/imm8
1447 74/jump-if-zero break/disp8
1448 0d/or-eax-with 0xffffff00/imm32
1449 }
1450
1451 {
1452 f6 0/subop/test-bits %dl 0x20/imm8
1453 74/jump-if-zero break/disp8
1454 81 1/subop/or %ecx 0xffffff00/imm32
1455 }
1456 $read-mouse-event:end:
1457
1458 5b/pop-to-ebx
1459 5a/pop-to-edx
1460
1461 89/<- %esp 5/r32/ebp
1462 5d/pop-to-ebp
1463 c3/return
1464
1465 +--147 lines: # mouse helpers -----------------------------------------------------------------------------------------------------------------------------------------------------------
1612
1613