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 0x00070000/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
895
896
897
898
899 Primary-bus-secondary-drive:
900
901 0x1f7/imm32
902
903 0x1f7/imm32
904
905 0x3f6/imm32
906
907 0x1f1/imm32
908
909 0x1f6/imm32
910
911 0x1f2/imm32
912
913 0x1f3/imm32
914
915 0x1f4/imm32
916
917 0x1f5/imm32
918
919 0x1f0/imm32
920
921 0xf0/imm32
922
923 == code
924
925 load-sectors:
926
927 55/push-ebp
928 89/<- %ebp 4/r32/esp
929
930 50/push-eax
931 51/push-ecx
932 52/push-edx
933
934 (drive-exists? *(ebp+8))
935 3d/compare-eax-and 0/imm32/false
936 0f 84/jump-if-= $load-sectors:end/disp32
937
938 (ata-drive-select *(ebp+8) *(ebp+0xc))
939 (clear-ata-error *(ebp+8))
940 (ata-sector-count *(ebp+8) *(ebp+0x10))
941 (ata-lba *(ebp+8) *(ebp+0xc))
942 (ata-command *(ebp+8) 0x20)
943
944 {
945
946
947 (while-ata-busy *(ebp+8))
948 (until-ata-data-available *(ebp+8))
949
950
951 8b/-> *(ebp+8) 0/r32/eax
952 8b/-> *(eax+0x24) 2/r32/edx
953
954 31/xor %eax 0/r32/eax
955 b9/copy-to-ecx 0x200/imm32
956 {
957 81 7/subop/compare %ecx 0/imm32
958 74/jump-if-= break/disp8
959 66 ed/read-port-dx-into-ax
960
961 (append-byte *(ebp+0x14) %eax)
962 49/decrement-ecx
963 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
964 (append-byte *(ebp+0x14) %eax)
965 49/decrement-ecx
966 eb/jump loop/disp8
967 }
968
969 ff 1/subop/decrement *(ebp+0x10)
970
971 81 7/subop/compare *(ebp+0x10) 0/imm32
972 7e/jump-if-<= break/disp8
973 (wait-400ns *(ebp+8))
974
975 e9/jump loop/disp32
976 }
977 $load-sectors:end:
978
979 5a/pop-to-edx
980 59/pop-to-ecx
981 58/pop-to-eax
982
983 89/<- %esp 5/r32/ebp
984 5d/pop-to-ebp
985 c3/return
986
987 store-sectors:
988
989 55/push-ebp
990 89/<- %ebp 4/r32/esp
991
992 50/push-eax
993 51/push-ecx
994 52/push-edx
995 53/push-ebx
996
997 (drive-exists? *(ebp+8))
998 3d/compare-eax-and 0/imm32/false
999 0f 84/jump-if-= $store-sectors:end/disp32
1000
1001 (ata-drive-select *(ebp+8) *(ebp+0xc))
1002 (clear-ata-error *(ebp+8))
1003 (ata-sector-count *(ebp+8) *(ebp+0x10))
1004 (ata-lba *(ebp+8) *(ebp+0xc))
1005 (ata-command *(ebp+8) 0x30)
1006
1007
1008
1009 {
1010
1011 (while-ata-busy *(ebp+8))
1012 (until-ata-ready-for-data *(ebp+8))
1013
1014 8b/-> *(ebp+8) 0/r32/eax
1015 8b/-> *(eax+0x24) 2/r32/edx
1016
1017 b9/copy-to-ecx 0x200/imm32
1018
1019
1020 bb/copy-to-ebx 0xffff/imm32
1021
1022 $store-sectors:store-sector:
1023 {
1024 81 7/subop/compare %ecx 0/imm32
1025 74/jump-if-= break/disp8
1026
1027 (stream-empty? *(ebp+0x14))
1028 3d/compare-eax-and 0/imm32/false
1029 75/jump-if-!= break/disp8
1030
1031 (read-byte *(ebp+0x14))
1032
1033 81 7/subop/compare %ebx 0xff/imm32
1034 {
1035 7e/jump-if-<= break/disp8
1036 89/<- %ebx 0/r32/eax
1037 eb/jump $store-sectors:store-sector/disp8
1038 }
1039
1040 c1/shift 4/subop/left %eax 8/imm8
1041 09/or %eax 3/r32/ebx
1042 66 ef/write-ax-into-port-dx
1043 49/decrement-ecx
1044 49/decrement-ecx
1045
1046 bb/copy-to-ebx 0xffff/imm32
1047 eb/jump loop/disp8
1048 }
1049
1050
1051 81 7/subop/compare %ebx 0xff/imm32
1052 {
1053 7f/jump-if-> break/disp8
1054 89/<- %eax 3/r32/ebx
1055 66 ef/write-ax-into-port-dx
1056 49/decrement-ecx
1057 49/decrement-ecx
1058 }
1059
1060
1061 31/xor %eax 0/r32/eax
1062 {
1063 81 7/subop/compare %ecx 0/imm32
1064 74/jump-if-= break/disp8
1065 66 ef/write-ax-into-port-dx
1066 49/decrement-ecx
1067 49/decrement-ecx
1068 eb/jump loop/disp8
1069 }
1070
1071
1072 ff 1/subop/decrement *(ebp+0x10)
1073 81 7/subop/compare *(ebp+0x10) 0/imm32
1074 7e/jump-if-<= break/disp8
1075
1076 (wait-400ns *(ebp+8))
1077
1078 e9/jump loop/disp32
1079 }
1080
1081 (flush-ata-cache *(ebp+8))
1082
1083 $store-sectors:end:
1084
1085 5b/pop-to-ebx
1086 5a/pop-to-edx
1087 59/pop-to-ecx
1088 58/pop-to-eax
1089
1090 89/<- %esp 5/r32/ebp
1091 5d/pop-to-ebp
1092 c3/return
1093
1094 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393 read-mouse-event:
1394
1395 55/push-ebp
1396 89/<- %ebp 4/r32/esp
1397
1398 52/push-edx
1399 53/push-ebx
1400
1401 b8/copy-to-eax 0/imm32
1402 b9/copy-to-ecx 0/imm32
1403 (any-mouse-event?)
1404 3d/compare-eax-and 0/imm32/false
1405 74/jump-if-= $read-mouse-event:end/disp8
1406
1407 31/xor %eax 0/r32/eax
1408 e4/read-port-into-al 0x60/imm8
1409 89/<- %edx 0/r32/eax
1410 (wait-for-mouse-event)
1411
1412 31/xor %eax 0/r32/eax
1413 e4/read-port-into-al 0x60/imm8
1414 89/<- %ebx 0/r32/eax
1415 (wait-for-mouse-event)
1416
1417 31/xor %eax 0/r32/eax
1418 e4/read-port-into-al 0x60/imm8
1419 89/<- %ecx 0/r32/eax
1420
1421 89/<- %eax 3/r32/ebx
1422
1423 {
1424 f6 0/subop/test-bits %dl 0x10/imm8
1425 74/jump-if-zero break/disp8
1426 0d/or-eax-with 0xffffff00/imm32
1427 }
1428
1429 {
1430 f6 0/subop/test-bits %dl 0x20/imm8
1431 74/jump-if-zero break/disp8
1432 81 1/subop/or %ecx 0xffffff00/imm32
1433 }
1434 $read-mouse-event:end:
1435
1436 5b/pop-to-ebx
1437 5a/pop-to-edx
1438
1439 89/<- %esp 5/r32/ebp
1440 5d/pop-to-ebp
1441 c3/return
1442
1443 +--147 lines: # mouse helpers -----------------------------------------------------------------------------------------------------------------------------------------------------------
1590
1591