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 b4/copy-to-ah 2/imm8/read-drive
127
128 b5/copy-to-ch 0/imm8/cylinder
129 b6/copy-to-dh 8/imm8/head
130 b1/copy-to-cl 1/imm8/sector
131 b0/copy-to-al 0x7e/imm8/num-sectors
132
133 bb/copy-to-bx 0x46c0/imm16
134 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
135 bb/copy-to-bx 0/imm16
136 cd/syscall 0x13/imm8/bios-disk-services
137 0f 82/jump-if-carry disk_error/disp16
138
139
140 bb/copy-to-bx 0/imm16
141 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
142
143
144 b4/copy-to-ah 0x4f/imm8
145 b0/copy-to-al 2/imm8
146 bb/copy-to-bx 0x4105/imm16
147
148
149
150 cd/syscall 0x10/imm8/bios-video-services
151
152
153
154 b4/copy-to-ah 0x4f/imm8
155 b0/copy-to-al 1/imm8
156 b9/copy-to-cx 0x0105/imm16
157 bf/copy-to-di Video-mode-info/imm16
158 cd/syscall 0x10/imm8/bios-video-services
159
160
161
162
163
164
165 0f 01 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7ce0/disp16/gdt_descriptor
166
167 0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
168 66 83 1/subop/or 3/mod/direct 0/rm32/eax 1/imm8
169 0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
170
171
172
173 ea/jump-far-absolute 0x00087d00/disp32
174
175 disk_error:
176
177
178 bb/copy-to-bx 0xb800/imm16
179 8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
180 b0/copy-to-al 0x44/imm8/D
181 b4/copy-to-ah 0x0f/imm8/white-on-black
182 bb/copy-to-bx 0/imm16
183 89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax
184
185 {
186 eb/jump loop/disp8
187 }
188
189
190 == data 0x7ce0
191 gdt_descriptor:
192 0x17/imm16
193 gdt_start/imm32/start
194
195 gdt_start:
196
197 00 00 00 00 00 00 00 00
198
199 ff ff
200 00 00 00
201 9a
202
203 cf
204
205 00
206
207 ff ff
208 00 00 00
209 92
210
211 cf
212 00
213
214
215
216
217 == code 0x7d00
218 initialize_32bit_mode:
219 66 b8/copy-to-ax 0x10/imm16
220 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
221 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
222 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
223 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
224 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
225
226 bc/copy-to-esp 0x02000000/imm32
227
228
229
230
231
232 0f 01 3/subop/lidt 0/mod/indirect 5/rm32/use-disp32 0x7e00/disp32/idt_descriptor
233
234
235
236
237
238
239
240
241
242
243
244 b0/copy-to-al 0xfc/imm8
245 e6/write-al-into-port 0x21/imm8
246
247 fb/enable-interrupts
248
249 (initialize-mouse)
250
251
252 db/floating-point-coprocessor e3/initialize
253
254 0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
255
256 0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
257
258 0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
259
260 e9/jump Entry/disp32
261
262 == boot-sector-marker 0x7dfe
263
264 55 aa
265
266
267
268 == data 0x7e00
269 idt_descriptor:
270 ff 03
271 idt_start/imm32/start
272
273 +-- 55 lines: # interrupt descriptor table ----------------------------------------------------------------------------------------------------------------------------------------------
328
329 == code
330
331 null-interrupt-handler:
332
333
334
335 fa/disable-interrupts
336 60/push-all-registers
337 9c/push-flags
338
339 b0/copy-to-al 0x20/imm8
340 e6/write-al-into-port 0x20/imm8
341 31/xor %eax 0/r32/eax
342 $null-interrupt-handler:epilogue:
343
344 9d/pop-flags
345 61/pop-all-registers
346 fb/enable-interrupts
347 cf/return-from-interrupt
348
349 timer-interrupt-handler:
350
351
352
353 fa/disable-interrupts
354 60/push-all-registers
355 9c/push-flags
356
357 b0/copy-to-al 0x20/imm8
358 e6/write-al-into-port 0x20/imm8
359 31/xor %eax 0/r32/eax
360 $timer-interrupt-handler:epilogue:
361
362 9d/pop-flags
363 61/pop-all-registers
364 fb/enable-interrupts
365 cf/return-from-interrupt
366
367 keyboard-interrupt-handler:
368
369 fa/disable-interrupts
370 60/push-all-registers
371 9c/push-flags
372
373 b0/copy-to-al 0x20/imm8
374 e6/write-al-into-port 0x20/imm8
375 31/xor %eax 0/r32/eax
376
377 e4/read-port-into-al 0x64/imm8
378 a8/test-bits-in-al 0x01/imm8
379 0f 84/jump-if-not-set $keyboard-interrupt-handler:epilogue/disp32
380
381
382 31/xor %ecx 1/r32/ecx
383 8a/byte-> *Keyboard-buffer:write 1/r32/cl
384 81 0/subop/add %ecx Keyboard-buffer:data/imm32
385
386 8a/byte-> *ecx 0/r32/al
387
388 3c/compare-al-and 0/imm8
389 0f 85/jump-if-!= $keyboard-interrupt-handler:epilogue/disp32
390
391 e4/read-port-into-al 0x60/imm8
392
393
394 {
395 3c/compare-al-and 0xaa/imm8
396 75/jump-if-!= break/disp8
397
398 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
399 }
400
401 {
402 3c/compare-al-and 0xb6/imm8
403 75/jump-if-!= break/disp8
404
405 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
406 }
407
408 {
409 3c/compare-al-and 0x9d/imm8
410 75/jump-if-!= break/disp8
411
412 c7 0/subop/copy *Keyboard-ctrl-pressed? 0/imm32
413 }
414
415 50/push-eax
416 24/and-al-with 0x80/imm8
417 3c/compare-al-and 0/imm8
418 58/pop-to-eax
419 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
420
421
422 {
423 3c/compare-al-and 0x2a/imm8
424 75/jump-if-!= break/disp8
425
426 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
427
428 eb/jump $keyboard-interrupt-handler:epilogue/disp8
429 }
430
431 {
432 3c/compare-al-and 0x36/imm8
433 75/jump-if-!= break/disp8
434
435 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
436
437 eb/jump $keyboard-interrupt-handler:epilogue/disp8
438 }
439
440 {
441 3c/compare-al-and 0x1d/imm8
442 75/jump-if-!= break/disp8
443
444 c7 0/subop/copy *Keyboard-ctrl-pressed? 1/imm32
445
446 eb/jump $keyboard-interrupt-handler:epilogue/disp8
447 }
448
449
450 {
451 81 7/subop/compare *Keyboard-shift-pressed? 0/imm32
452 74/jump-if-= break/disp8
453
454 05/add-to-eax Keyboard-shift-map/imm32
455 8a/byte-> *eax 0/r32/al
456 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
457 }
458
459 {
460 81 7/subop/compare *Keyboard-ctrl-pressed? 0/imm32
461 74/jump-if-= break/disp8
462 05/add-to-eax Keyboard-ctrl-map/imm32
463 8a/byte-> *eax 0/r32/al
464 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
465 }
466
467 05/add-to-eax Keyboard-normal-map/imm32
468 8a/byte-> *eax 0/r32/al
469 $keyboard-interrupt-handler:select-map-done:
470
471 {
472 3c/compare-al-and 0/imm8
473 74/jump-if-= break/disp8
474
475 88/<- *ecx 0/r32/al
476
477 fe/increment-byte *Keyboard-buffer:write
478
479 80 4/subop/and-byte *Keyboard-buffer:write 0x0f/imm8
480 }
481 $keyboard-interrupt-handler:epilogue:
482
483 9d/pop-flags
484 61/pop-all-registers
485 fb/enable-interrupts
486 cf/return-from-interrupt
487
488 == data
489 Keyboard-shift-pressed?:
490 0/imm32
491
492 Keyboard-ctrl-pressed?:
493 0/imm32
494
495
496 Keyboard-buffer:write:
497 0/imm32
498 Keyboard-buffer:read:
499 0/imm32
500 Keyboard-buffer:data:
501 00 00 00 00
502 00 00 00 00
503 00 00 00 00
504 00 00 00 00
505
506 +-- 95 lines: # Keyboard maps for translating keys to ASCII -----------------------------------------------------------------------------------------------------------------------------
601
602 Video-mode-info:
603 +-- 53 lines: # video mode info ---------------------------------------------------------------------------------------------------------------------------------------------------------
656
657 Font:
658 +--236 lines: # Bitmaps for some ASCII characters (soon Unicode) ------------------------------------------------------------------------------------------------------------------------
894
895
896
897
898
899
900
901
902
903
904 == data
905
906
907
908 Primary-bus-primary-drive:
909
910 0x1f7/imm32
911
912 0x1f7/imm32
913
914 0x3f6/imm32
915
916 0x1f1/imm32
917
918 0x1f6/imm32
919
920 0x1f2/imm32
921
922 0x1f3/imm32
923
924 0x1f4/imm32
925
926 0x1f5/imm32
927
928 0x1f0/imm32
929
930 0xe0/imm32
931
932
933
934 Primary-bus-secondary-drive:
935
936 0x1f7/imm32
937
938 0x1f7/imm32
939
940 0x3f6/imm32
941
942 0x1f1/imm32
943
944 0x1f6/imm32
945
946 0x1f2/imm32
947
948 0x1f3/imm32
949
950 0x1f4/imm32
951
952 0x1f5/imm32
953
954 0x1f0/imm32
955
956 0xf0/imm32
957
958 == code
959
960 load-sectors:
961
962 55/push-ebp
963 89/<- %ebp 4/r32/esp
964
965 50/push-eax
966 51/push-ecx
967 52/push-edx
968
969 (drive-exists? *(ebp+8))
970 3d/compare-eax-and 0/imm32/false
971 0f 84/jump-if-= $load-sectors:end/disp32
972
973 (ata-drive-select *(ebp+8) *(ebp+0xc))
974 (clear-ata-error *(ebp+8))
975 (ata-sector-count *(ebp+8) *(ebp+0x10))
976 (ata-lba *(ebp+8) *(ebp+0xc))
977 (ata-command *(ebp+8) 0x20)
978
979 {
980
981
982
983 (while-ata-busy *(ebp+8))
984 (until-ata-data-available *(ebp+8))
985
986
987 8b/-> *(ebp+8) 0/r32/eax
988 8b/-> *(eax+0x24) 2/r32/edx
989
990 31/xor %eax 0/r32/eax
991 b9/copy-to-ecx 0x200/imm32
992 {
993 81 7/subop/compare %ecx 0/imm32
994 74/jump-if-= break/disp8
995 66 ed/read-port-dx-into-ax
996
997 (append-byte *(ebp+0x14) %eax)
998 49/decrement-ecx
999 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
1000 (append-byte *(ebp+0x14) %eax)
1001 49/decrement-ecx
1002 eb/jump loop/disp8
1003 }
1004
1005 ff 1/subop/decrement *(ebp+0x10)
1006
1007 81 7/subop/compare *(ebp+0x10) 0/imm32
1008 7e/jump-if-<= break/disp8
1009 (wait-400ns *(ebp+8))
1010
1011 e9/jump loop/disp32
1012 }
1013 $load-sectors:end:
1014
1015 5a/pop-to-edx
1016 59/pop-to-ecx
1017 58/pop-to-eax
1018
1019 89/<- %esp 5/r32/ebp
1020 5d/pop-to-ebp
1021 c3/return
1022
1023 store-sectors:
1024
1025 55/push-ebp
1026 89/<- %ebp 4/r32/esp
1027
1028 50/push-eax
1029 51/push-ecx
1030 52/push-edx
1031 53/push-ebx
1032
1033 (drive-exists? *(ebp+8))
1034 3d/compare-eax-and 0/imm32/false
1035 0f 84/jump-if-= $store-sectors:end/disp32
1036
1037 (ata-drive-select *(ebp+8) *(ebp+0xc))
1038 (clear-ata-error *(ebp+8))
1039 (ata-sector-count *(ebp+8) *(ebp+0x10))
1040 (ata-lba *(ebp+8) *(ebp+0xc))
1041 (ata-command *(ebp+8) 0x30)
1042
1043
1044
1045 {
1046
1047 (while-ata-busy *(ebp+8))
1048 (until-ata-ready-for-data *(ebp+8))
1049
1050 8b/-> *(ebp+8) 0/r32/eax
1051 8b/-> *(eax+0x24) 2/r32/edx
1052
1053 b9/copy-to-ecx 0x200/imm32
1054
1055
1056 bb/copy-to-ebx 0xffff/imm32
1057
1058 $store-sectors:store-sector:
1059 {
1060 81 7/subop/compare %ecx 0/imm32
1061 74/jump-if-= break/disp8
1062
1063 (stream-empty? *(ebp+0x14))
1064 3d/compare-eax-and 0/imm32/false
1065 75/jump-if-!= break/disp8
1066
1067 (read-byte *(ebp+0x14))
1068
1069 81 7/subop/compare %ebx 0xff/imm32
1070 {
1071 7e/jump-if-<= break/disp8
1072 89/<- %ebx 0/r32/eax
1073 eb/jump $store-sectors:store-sector/disp8
1074 }
1075
1076 c1/shift 4/subop/left %eax 8/imm8
1077 09/or %eax 3/r32/ebx
1078 66 ef/write-ax-into-port-dx
1079 49/decrement-ecx
1080 49/decrement-ecx
1081
1082 bb/copy-to-ebx 0xffff/imm32
1083 eb/jump loop/disp8
1084 }
1085
1086
1087 81 7/subop/compare %ebx 0xff/imm32
1088 {
1089 7f/jump-if-> break/disp8
1090 89/<- %eax 3/r32/ebx
1091 66 ef/write-ax-into-port-dx
1092 49/decrement-ecx
1093 49/decrement-ecx
1094 }
1095
1096
1097 31/xor %eax 0/r32/eax
1098 {
1099 81 7/subop/compare %ecx 0/imm32
1100 74/jump-if-= break/disp8
1101 66 ef/write-ax-into-port-dx
1102 49/decrement-ecx
1103 49/decrement-ecx
1104 eb/jump loop/disp8
1105 }
1106
1107
1108 ff 1/subop/decrement *(ebp+0x10)
1109 81 7/subop/compare *(ebp+0x10) 0/imm32
1110 7e/jump-if-<= break/disp8
1111
1112 (wait-400ns *(ebp+8))
1113
1114 e9/jump loop/disp32
1115 }
1116
1117 (flush-ata-cache *(ebp+8))
1118
1119 $store-sectors:end:
1120
1121 5b/pop-to-ebx
1122 5a/pop-to-edx
1123 59/pop-to-ecx
1124 58/pop-to-eax
1125
1126 89/<- %esp 5/r32/ebp
1127 5d/pop-to-ebp
1128 c3/return
1129
1130 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429 read-mouse-event:
1430
1431 55/push-ebp
1432 89/<- %ebp 4/r32/esp
1433
1434 52/push-edx
1435 53/push-ebx
1436
1437 b8/copy-to-eax 0/imm32
1438 b9/copy-to-ecx 0/imm32
1439 (any-mouse-event?)
1440 3d/compare-eax-and 0/imm32/false
1441 74/jump-if-= $read-mouse-event:end/disp8
1442
1443 31/xor %eax 0/r32/eax
1444 e4/read-port-into-al 0x60/imm8
1445 89/<- %edx 0/r32/eax
1446 (wait-for-mouse-event)
1447
1448 31/xor %eax 0/r32/eax
1449 e4/read-port-into-al 0x60/imm8
1450 89/<- %ebx 0/r32/eax
1451 (wait-for-mouse-event)
1452
1453 31/xor %eax 0/r32/eax
1454 e4/read-port-into-al 0x60/imm8
1455 89/<- %ecx 0/r32/eax
1456
1457 89/<- %eax 3/r32/ebx
1458
1459 {
1460 f6 0/subop/test-bits %dl 0x10/imm8
1461 74/jump-if-zero break/disp8
1462 0d/or-eax-with 0xffffff00/imm32
1463 }
1464
1465 {
1466 f6 0/subop/test-bits %dl 0x20/imm8
1467 74/jump-if-zero break/disp8
1468 81 1/subop/or %ecx 0xffffff00/imm32
1469 }
1470 $read-mouse-event:end:
1471
1472 5b/pop-to-ebx
1473 5a/pop-to-edx
1474
1475 89/<- %esp 5/r32/ebp
1476 5d/pop-to-ebp
1477 c3/return
1478
1479 +--147 lines: # mouse helpers -----------------------------------------------------------------------------------------------------------------------------------------------------------
1626
1627