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 == code
25
26
27
28
29
30
31
32
33
34 fa/disable-interrupts
35
36
37 b8/copy-to-ax 0/imm16
38 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
39 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
40 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
41 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
42
43
44
45
46
47 b8/copy-to-ax 0x7000/imm16
48 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
49 bc/copy-to-esp 0/imm16
50
51
52
53 {
54 e4/read-port-into-al 0x64/imm8
55 a8/test-bits-in-al 0x02/imm8
56 75/jump-if-!zero loop/disp8
57 b0/copy-to-al 0xd1/imm8
58 e6/write-al-into-port 0x64/imm8
59 }
60 {
61 e4/read-port-into-al 0x64/imm8
62 a8/test-bits-in-al 0x02/imm8
63 75/jump-if-!zero loop/disp8
64 b0/copy-to-al 0xdf/imm8
65 e6/write-al-into-port 0x64/imm8
66 }
67
68
69 b4/copy-to-ah 2/imm8/read-drive
70
71 b5/copy-to-ch 0/imm8/cylinder
72 b6/copy-to-dh 0/imm8/head
73 b1/copy-to-cl 2/imm8/sector
74 b0/copy-to-al 0x7d/imm8/num-sectors
75
76 bb/copy-to-bx 0/imm16
77 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
78 bb/copy-to-bx 0x7e00/imm16
79 cd/syscall 0x13/imm8/bios-disk-services
80 0f 82/jump-if-carry disk_error/disp16
81
82
83 b4/copy-to-ah 2/imm8/read-drive
84
85 b5/copy-to-ch 0/imm8/cylinder
86 b6/copy-to-dh 2/imm8/head
87 b1/copy-to-cl 1/imm8/sector
88 b0/copy-to-al 0x7e/imm8/num-sectors
89
90 bb/copy-to-bx 0x1780/imm16
91 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
92 bb/copy-to-bx 0/imm16
93 cd/syscall 0x13/imm8/bios-disk-services
94 0f 82/jump-if-carry disk_error/disp16
95
96
97 b4/copy-to-ah 2/imm8/read-drive
98
99 b5/copy-to-ch 0/imm8/cylinder
100 b6/copy-to-dh 4/imm8/head
101 b1/copy-to-cl 1/imm8/sector
102 b0/copy-to-al 0x7e/imm8/num-sectors
103
104 bb/copy-to-bx 0x2740/imm16
105 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
106 bb/copy-to-bx 0/imm16
107 cd/syscall 0x13/imm8/bios-disk-services
108 0f 82/jump-if-carry disk_error/disp16
109
110
111 bb/copy-to-bx 0/imm16
112 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
113
114
115 b4/copy-to-ah 0x4f/imm8
116 b0/copy-to-al 2/imm8
117 bb/copy-to-bx 0x4105/imm16
118
119
120
121 cd/syscall 0x10/imm8/bios-video-services
122
123
124
125 b4/copy-to-ah 0x4f/imm8
126 b0/copy-to-al 1/imm8
127 b9/copy-to-cx 0x0105/imm16
128 bf/copy-to-di Video-mode-info/imm16
129 cd/syscall 0x10/imm8/bios-video-services
130
131
132
133
134
135
136 0f 01 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7ce0/disp16/gdt_descriptor
137
138 0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
139 66 83 1/subop/or 3/mod/direct 0/rm32/eax 1/imm8
140 0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
141
142
143
144 ea/jump-far-absolute 0x00087d00/disp32
145
146 disk_error:
147
148
149 bb/copy-to-bx 0xb800/imm16
150 8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
151 b0/copy-to-al 0x44/imm8/D
152 b4/copy-to-ah 0x0f/imm8/white-on-black
153 bb/copy-to-bx 0/imm16
154 89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax
155
156 {
157 eb/jump loop/disp8
158 }
159
160
161 == data 0x7ce0
162 gdt_descriptor:
163 0x17/imm16
164 gdt_start/imm32/start
165
166 gdt_start:
167
168 00 00 00 00 00 00 00 00
169
170 ff ff
171 00 00 00
172 9a
173
174 cf
175
176 00
177
178 ff ff
179 00 00 00
180 92
181
182 cf
183 00
184
185
186
187
188 == code 0x7d00
189 initialize_32bit_mode:
190 66 b8/copy-to-ax 0x10/imm16
191 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
192 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
193 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
194 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
195 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
196
197 bc/copy-to-esp 0x00070000/imm32
198
199
200
201
202
203 0f 01 3/subop/lidt 0/mod/indirect 5/rm32/use-disp32 0x7e00/disp32/idt_descriptor
204
205
206
207
208
209
210
211
212
213
214
215 b0/copy-to-al 0xfc/imm8
216 e6/write-al-into-port 0x21/imm8
217
218 fb/enable-interrupts
219
220 (initialize-mouse)
221
222
223 db/floating-point-coprocessor e3/initialize
224
225 0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
226
227 0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
228
229 0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
230
231 e9/jump Entry/disp32
232
233 == boot-sector-marker 0x7dfe
234
235 55 aa
236
237
238
239 == data 0x7e00
240 idt_descriptor:
241 ff 03
242 idt_start/imm32/start
243
244 +-- 55 lines: # interrupt descriptor table ----------------------------------------------------------------------------------------------------------------------------------------------
299
300 == code
301
302 null-interrupt-handler:
303
304
305
306 fa/disable-interrupts
307 60/push-all-registers
308 9c/push-flags
309
310 b0/copy-to-al 0x20/imm8
311 e6/write-al-into-port 0x20/imm8
312 31/xor %eax 0/r32/eax
313 $null-interrupt-handler:epilogue:
314
315 9d/pop-flags
316 61/pop-all-registers
317 fb/enable-interrupts
318 cf/return-from-interrupt
319
320 timer-interrupt-handler:
321
322
323
324 fa/disable-interrupts
325 60/push-all-registers
326 9c/push-flags
327
328 b0/copy-to-al 0x20/imm8
329 e6/write-al-into-port 0x20/imm8
330 31/xor %eax 0/r32/eax
331 $timer-interrupt-handler:epilogue:
332
333 9d/pop-flags
334 61/pop-all-registers
335 fb/enable-interrupts
336 cf/return-from-interrupt
337
338 keyboard-interrupt-handler:
339
340 fa/disable-interrupts
341 60/push-all-registers
342 9c/push-flags
343
344 b0/copy-to-al 0x20/imm8
345 e6/write-al-into-port 0x20/imm8
346 31/xor %eax 0/r32/eax
347
348 e4/read-port-into-al 0x64/imm8
349 a8/test-bits-in-al 0x01/imm8
350 74/jump-if-not-set $keyboard-interrupt-handler:epilogue/disp8
351
352
353 31/xor %ecx 1/r32/ecx
354 8a/byte-> *Keyboard-buffer:write 1/r32/cl
355 81 0/subop/add %ecx Keyboard-buffer:data/imm32
356
357 8a/byte-> *ecx 0/r32/al
358
359 3c/compare-al-and 0/imm8
360 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
361
362 e4/read-port-into-al 0x60/imm8
363
364
365 {
366 3c/compare-al-and 0xaa/imm8
367 75/jump-if-!= break/disp8
368
369 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
370 }
371
372 {
373 3c/compare-al-and 0xb6/imm8
374 75/jump-if-!= break/disp8
375
376 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
377 }
378
379 {
380 3c/compare-al-and 0x9d/imm8
381 75/jump-if-!= break/disp8
382
383 c7 0/subop/copy *Keyboard-ctrl-pressed? 0/imm32
384 }
385
386 50/push-eax
387 24/and-al-with 0x80/imm8
388 3c/compare-al-and 0/imm8
389 58/pop-to-eax
390 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
391
392
393 {
394 3c/compare-al-and 0x2a/imm8
395 75/jump-if-!= break/disp8
396
397 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
398
399 eb/jump $keyboard-interrupt-handler:epilogue/disp8
400 }
401
402 {
403 3c/compare-al-and 0x36/imm8
404 75/jump-if-!= break/disp8
405
406 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
407
408 eb/jump $keyboard-interrupt-handler:epilogue/disp8
409 }
410
411 {
412 3c/compare-al-and 0x1d/imm8
413 75/jump-if-!= break/disp8
414
415 c7 0/subop/copy *Keyboard-ctrl-pressed? 1/imm32
416
417 eb/jump $keyboard-interrupt-handler:epilogue/disp8
418 }
419
420
421 {
422 81 7/subop/compare *Keyboard-shift-pressed? 0/imm32
423 74/jump-if-= break/disp8
424
425 05/add-to-eax Keyboard-shift-map/imm32
426 8a/byte-> *eax 0/r32/al
427 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
428 }
429
430 {
431 81 7/subop/compare *Keyboard-ctrl-pressed? 0/imm32
432 74/jump-if-= break/disp8
433 05/add-to-eax Keyboard-ctrl-map/imm32
434 8a/byte-> *eax 0/r32/al
435 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
436 }
437
438 05/add-to-eax Keyboard-normal-map/imm32
439 8a/byte-> *eax 0/r32/al
440 $keyboard-interrupt-handler:select-map-done:
441
442 {
443 3c/compare-al-and 0/imm8
444 74/jump-if-= break/disp8
445
446 88/<- *ecx 0/r32/al
447
448 fe/increment-byte *Keyboard-buffer:write
449
450 80 4/subop/and-byte *Keyboard-buffer:write 0x0f/imm8
451 }
452 $keyboard-interrupt-handler:epilogue:
453
454 9d/pop-flags
455 61/pop-all-registers
456 fb/enable-interrupts
457 cf/return-from-interrupt
458
459 == data
460 Keyboard-shift-pressed?:
461 0/imm32
462
463 Keyboard-ctrl-pressed?:
464 0/imm32
465
466
467 Keyboard-buffer:write:
468 0/imm32
469 Keyboard-buffer:read:
470 0/imm32
471 Keyboard-buffer:data:
472 00 00 00 00
473 00 00 00 00
474 00 00 00 00
475 00 00 00 00
476
477 +-- 95 lines: # Keyboard maps for translating keys to ASCII -----------------------------------------------------------------------------------------------------------------------------
572
573 Video-mode-info:
574 +-- 53 lines: # video mode info ---------------------------------------------------------------------------------------------------------------------------------------------------------
627
628 Font:
629 +--236 lines: # Bitmaps for some ASCII characters (soon Unicode) ------------------------------------------------------------------------------------------------------------------------
865
866
867
868
869
870
871
872
873
874
875 == data
876
877
878
879
880
881
882
883
884 Primary-bus-secondary-drive:
885
886 0x1f7/imm32
887
888 0x1f7/imm32
889
890 0x3f6/imm32
891
892 0x1f1/imm32
893
894 0x1f6/imm32
895
896 0x1f2/imm32
897
898 0x1f3/imm32
899
900 0x1f4/imm32
901
902 0x1f5/imm32
903
904 0x1f0/imm32
905
906 0xf0/imm32
907
908 == code
909
910 load-sector:
911
912 55/push-ebp
913 89/<- %ebp 4/r32/esp
914
915 50/push-eax
916 51/push-ecx
917 52/push-edx
918
919 (drive-exists? *(ebp+8))
920 3d/compare-eax-and 0/imm32/false
921 0f 84/jump-if-= $load-sector:end/disp32
922
923 (ata-drive-select *(ebp+8) *(ebp+0xc))
924 (clear-ata-error *(ebp+8))
925 (ata-sector-count *(ebp+8) 1)
926 (ata-lba *(ebp+8) *(ebp+0xc))
927 (ata-command *(ebp+8) 0x20)
928
929 (while-ata-busy *(ebp+8))
930 (until-ata-data-available *(ebp+8))
931
932 8b/-> *(ebp+8) 0/r32/eax
933 8b/-> *(eax+0x24) 2/r32/edx
934
935 31/xor %eax 0/r32/eax
936 b9/copy-to-ecx 0x200/imm32
937 {
938 81 7/subop/compare %ecx 0/imm32
939 74/jump-if-= break/disp8
940 66 ed/read-port-dx-into-ax
941
942 (append-byte *(ebp+0x10) %eax)
943 49/decrement-ecx
944 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
945 (append-byte *(ebp+0x10) %eax)
946 49/decrement-ecx
947 eb/jump loop/disp8
948 }
949 $load-sector:end:
950
951 5a/pop-to-edx
952 59/pop-to-ecx
953 58/pop-to-eax
954
955 89/<- %esp 5/r32/ebp
956 5d/pop-to-ebp
957 c3/return
958
959 store-sector:
960
961 55/push-ebp
962 89/<- %ebp 4/r32/esp
963
964 50/push-eax
965 51/push-ecx
966 52/push-edx
967 53/push-ebx
968
969 (drive-exists? *(ebp+8))
970 3d/compare-eax-and 0/imm32/false
971 0f 84/jump-if-= $store-sector:end/disp32
972
973 (ata-drive-select *(ebp+8) *(ebp+0xc))
974 (clear-ata-error *(ebp+8))
975 (ata-sector-count *(ebp+8) 1)
976 (ata-lba *(ebp+8) *(ebp+0xc))
977 (ata-command *(ebp+8) 0x30)
978
979 (while-ata-busy *(ebp+8))
980 (until-ata-ready-for-data *(ebp+8))
981
982 8b/-> *(ebp+8) 0/r32/eax
983 8b/-> *(eax+0x24) 2/r32/edx
984
985 b9/copy-to-ecx 0x200/imm32
986
987
988 bb/copy-to-ebx 0xffff/imm32
989 $store-sector:loop:
990 {
991 81 7/subop/compare %ecx 0/imm32
992 74/jump-if-= break/disp8
993
994 (stream-empty? *(ebp+0x10))
995 3d/compare-eax-and 0/imm32/false
996 75/jump-if-!= break/disp8
997
998 (read-byte *(ebp+0x10))
999
1000 81 7/subop/compare %ebx 0xff/imm32
1001 {
1002 7e/jump-if-<= break/disp8
1003 89/<- %ebx 0/r32/eax
1004 eb/jump $store-sector:loop/disp8
1005 }
1006
1007 c1/shift 4/subop/left %eax 8/imm8
1008 09/or %eax 3/r32/ebx
1009 66 ef/write-ax-into-port-dx
1010 49/decrement-ecx
1011 49/decrement-ecx
1012
1013 bb/copy-to-ebx 0xffff/imm32
1014 eb/jump loop/disp8
1015 }
1016
1017 81 7/subop/compare %ebx 0xff/imm32
1018 {
1019 7f/jump-if-> break/disp8
1020 89/<- %eax 3/r32/ebx
1021 66 ef/write-ax-into-port-dx
1022 49/decrement-ecx
1023 49/decrement-ecx
1024 }
1025
1026 31/xor %eax 0/r32/eax
1027 {
1028 81 7/subop/compare %ecx 0/imm32
1029 74/jump-if-= break/disp8
1030 66 ef/write-ax-into-port-dx
1031 49/decrement-ecx
1032 49/decrement-ecx
1033 eb/jump loop/disp8
1034 }
1035 $store-sector:end:
1036
1037 5b/pop-to-ebx
1038 5a/pop-to-edx
1039 59/pop-to-ecx
1040 58/pop-to-eax
1041
1042 89/<- %esp 5/r32/ebp
1043 5d/pop-to-ebp
1044 c3/return
1045
1046 +--235 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291 read-mouse-event:
1292
1293 55/push-ebp
1294 89/<- %ebp 4/r32/esp
1295
1296 52/push-edx
1297 53/push-ebx
1298
1299 b8/copy-to-eax 0/imm32
1300 b9/copy-to-ecx 0/imm32
1301 (any-mouse-event?)
1302 3d/compare-eax-and 0/imm32/false
1303 74/jump-if-= $read-mouse-event:end/disp8
1304
1305 31/xor %eax 0/r32/eax
1306 e4/read-port-into-al 0x60/imm8
1307 89/<- %edx 0/r32/eax
1308 (wait-for-mouse-event)
1309
1310 31/xor %eax 0/r32/eax
1311 e4/read-port-into-al 0x60/imm8
1312 89/<- %ebx 0/r32/eax
1313 (wait-for-mouse-event)
1314
1315 31/xor %eax 0/r32/eax
1316 e4/read-port-into-al 0x60/imm8
1317 89/<- %ecx 0/r32/eax
1318
1319 89/<- %eax 3/r32/ebx
1320
1321 {
1322 f6 0/subop/test-bits %dl 0x10/imm8
1323 74/jump-if-zero break/disp8
1324 0d/or-eax-with 0xffffff00/imm32
1325 }
1326
1327 {
1328 f6 0/subop/test-bits %dl 0x20/imm8
1329 74/jump-if-zero break/disp8
1330 81 1/subop/or %ecx 0xffffff00/imm32
1331 }
1332 $read-mouse-event:end:
1333
1334 5b/pop-to-ebx
1335 5a/pop-to-edx
1336
1337 89/<- %esp 5/r32/ebp
1338 5d/pop-to-ebp
1339 c3/return
1340
1341 +--147 lines: # mouse helpers -----------------------------------------------------------------------------------------------------------------------------------------------------------
1488
1489