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