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