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
26 == code
27
28
29
30
31
32
33
34
35
36 fa/disable-interrupts
37
38
39 b8/copy-to-ax 0/imm16
40 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
41 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
42 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
43 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
44
45
46
47
48
49 b8/copy-to-ax 0x7000/imm16
50 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
51 bc/copy-to-esp 0/imm16
52
53
54
55 {
56 e4/read-port-into-al 0x64/imm8
57 a8/test-bits-in-al 0x02/imm8
58 75/jump-if-!zero loop/disp8
59 b0/copy-to-al 0xd1/imm8
60 e6/write-al-into-port 0x64/imm8
61 }
62 {
63 e4/read-port-into-al 0x64/imm8
64 a8/test-bits-in-al 0x02/imm8
65 75/jump-if-!zero loop/disp8
66 b0/copy-to-al 0xdf/imm8
67 e6/write-al-into-port 0x64/imm8
68 }
69
70
71 b4/copy-to-ah 2/imm8/read-drive
72
73 b5/copy-to-ch 0/imm8/cylinder
74 b6/copy-to-dh 0/imm8/head
75 b1/copy-to-cl 2/imm8/sector
76 b0/copy-to-al 0x7d/imm8/num-sectors
77
78 bb/copy-to-bx 0/imm16
79 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
80 bb/copy-to-bx 0x7e00/imm16
81 cd/syscall 0x13/imm8/bios-disk-services
82 0f 82/jump-if-carry disk_error/disp16
83
84
85 b4/copy-to-ah 2/imm8/read-drive
86
87 b5/copy-to-ch 0/imm8/cylinder
88 b6/copy-to-dh 2/imm8/head
89 b1/copy-to-cl 1/imm8/sector
90 b0/copy-to-al 0x7e/imm8/num-sectors
91
92 bb/copy-to-bx 0x1780/imm16
93 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
94 bb/copy-to-bx 0/imm16
95 cd/syscall 0x13/imm8/bios-disk-services
96 0f 82/jump-if-carry disk_error/disp16
97
98
99 b4/copy-to-ah 2/imm8/read-drive
100
101 b5/copy-to-ch 0/imm8/cylinder
102 b6/copy-to-dh 4/imm8/head
103 b1/copy-to-cl 1/imm8/sector
104 b0/copy-to-al 0x7e/imm8/num-sectors
105
106 bb/copy-to-bx 0x2740/imm16
107 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
108 bb/copy-to-bx 0/imm16
109 cd/syscall 0x13/imm8/bios-disk-services
110 0f 82/jump-if-carry disk_error/disp16
111
112
113 b4/copy-to-ah 2/imm8/read-drive
114
115 b5/copy-to-ch 0/imm8/cylinder
116 b6/copy-to-dh 6/imm8/head
117 b1/copy-to-cl 1/imm8/sector
118 b0/copy-to-al 0x7e/imm8/num-sectors
119
120 bb/copy-to-bx 0x3700/imm16
121 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
122 bb/copy-to-bx 0/imm16
123 cd/syscall 0x13/imm8/bios-disk-services
124 0f 82/jump-if-carry disk_error/disp16
125
126
127 b4/copy-to-ah 2/imm8/read-drive
128
129 b5/copy-to-ch 0/imm8/cylinder
130 b6/copy-to-dh 8/imm8/head
131 b1/copy-to-cl 1/imm8/sector
132 b0/copy-to-al 0x7e/imm8/num-sectors
133
134 bb/copy-to-bx 0x46c0/imm16
135 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
136 bb/copy-to-bx 0/imm16
137 cd/syscall 0x13/imm8/bios-disk-services
138 0f 82/jump-if-carry disk_error/disp16
139
140
141 b4/copy-to-ah 2/imm8/read-drive
142
143 b5/copy-to-ch 0/imm8/cylinder
144 b6/copy-to-dh 0xa/imm8/head
145 b1/copy-to-cl 1/imm8/sector
146 b0/copy-to-al 0x7e/imm8/num-sectors
147
148 bb/copy-to-bx 0x5680/imm16
149 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
150 bb/copy-to-bx 0/imm16
151 cd/syscall 0x13/imm8/bios-disk-services
152 0f 82/jump-if-carry disk_error/disp16
153
154
155 b4/copy-to-ah 2/imm8/read-drive
156
157 b5/copy-to-ch 0/imm8/cylinder
158 b6/copy-to-dh 0xc/imm8/head
159 b1/copy-to-cl 1/imm8/sector
160 b0/copy-to-al 0x7e/imm8/num-sectors
161
162 bb/copy-to-bx 0x6640/imm16
163 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
164 bb/copy-to-bx 0/imm16
165 cd/syscall 0x13/imm8/bios-disk-services
166 0f 82/jump-if-carry disk_error/disp16
167
168
169 b4/copy-to-ah 2/imm8/read-drive
170
171 b5/copy-to-ch 0/imm8/cylinder
172 b6/copy-to-dh 0xe/imm8/head
173 b1/copy-to-cl 1/imm8/sector
174 b0/copy-to-al 0x3f/imm8/num-sectors=63
175
176 bb/copy-to-bx 0x7600/imm16
177 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
178 bb/copy-to-bx 0/imm16
179 cd/syscall 0x13/imm8/bios-disk-services
180 0f 82/jump-if-carry disk_error/disp16
181
182
183
184
185 bb/copy-to-bx 0/imm16
186 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
187
188
189 b4/copy-to-ah 0x4f/imm8
190 b0/copy-to-al 2/imm8
191 bb/copy-to-bx 0x4105/imm16
192
193
194
195 cd/syscall 0x10/imm8/bios-video-services
196
197
198
199 b4/copy-to-ah 0x4f/imm8
200 b0/copy-to-al 1/imm8
201 b9/copy-to-cx 0x0105/imm16
202 bf/copy-to-di Video-mode-info/imm16
203 cd/syscall 0x10/imm8/bios-video-services
204
205
206
207
208
209
210 0f 01 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7de0/disp16/gdt_descriptor
211
212 0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
213 66 83 1/subop/or 3/mod/direct 0/rm32/eax 1/imm8
214 0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
215
216
217
218 ea/jump-far-absolute 0x00087e00/disp32
219
220 disk_error:
221
222
223 bb/copy-to-bx 0xb800/imm16
224 8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
225 b0/copy-to-al 0x44/imm8/D
226 b4/copy-to-ah 0x0f/imm8/white-on-black
227 bb/copy-to-bx 0/imm16
228 89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax
229
230 {
231 eb/jump loop/disp8
232 }
233
234
235 == data 0x7de0
236 gdt_descriptor:
237 0x17/imm16
238 gdt_start/imm32/start
239
240 gdt_start:
241
242 00 00 00 00 00 00 00 00
243
244 ff ff
245 00 00 00
246 9a
247
248 cf
249
250 00
251
252 ff ff
253 00 00 00
254 92
255
256 cf
257 00
258
259
260 == boot-sector-marker 0x7dfe
261
262 55 aa
263
264
265
266
267
268 == code 0x7e00
269 initialize_32bit_mode:
270 66 b8/copy-to-ax 0x10/imm16
271 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
272 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
273 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
274 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
275 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
276
277 bc/copy-to-esp 0x02000000/imm32
278
279
280 c7 0/subop/copy *0x00100000 0/imm32/read
281 c7 0/subop/copy *0x00100004 0/imm32/write
282 c7 0/subop/copy *0x00100008 0x00e00000/imm32/size
283 (load-sectors Primary-bus-primary-drive 0x2328 0x200 0x00100000)
284
285
286
287
288
289
290 0f 01 3/subop/lidt 0/mod/indirect 5/rm32/use-disp32 0x7f00/disp32/idt_descriptor
291
292
293
294
295
296
297
298
299
300
301
302 b0/copy-to-al 0xfc/imm8
303 e6/write-al-into-port 0x21/imm8
304
305 fb/enable-interrupts
306
307 (initialize-mouse)
308
309
310 db/floating-point-coprocessor e3/initialize
311
312 0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
313
314 0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
315
316 0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
317
318 e9/jump Entry/disp32
319
320 == data 0x7f00
321 idt_descriptor:
322 ff 03
323 idt_start/imm32/start
324
325 +-- 55 lines: # interrupt descriptor table ----------------------------------------------------------------------------------------------------------------------------------------------
380
381 == code
382
383 timer-interrupt-handler:
384
385 fa/disable-interrupts
386 60/push-all-registers
387 9c/push-flags
388
389 b0/copy-to-al 0x20/imm8
390 e6/write-al-into-port 0x20/imm8
391 31/xor %eax 0/r32/eax
392
393 ff 0/subop/increment *Timer-counter
394 $timer-interrupt-handler:epilogue:
395
396 9d/pop-flags
397 61/pop-all-registers
398 fb/enable-interrupts
399 cf/return-from-interrupt
400
401 == data
402 Timer-counter:
403 0/imm32
404
405 == code
406 keyboard-interrupt-handler:
407
408 fa/disable-interrupts
409 60/push-all-registers
410 9c/push-flags
411
412 b0/copy-to-al 0x20/imm8
413 e6/write-al-into-port 0x20/imm8
414 31/xor %eax 0/r32/eax
415
416 e4/read-port-into-al 0x64/imm8
417 a8/test-bits-in-al 0x01/imm8
418 0f 84/jump-if-not-set $keyboard-interrupt-handler:end/disp32
419
420
421 31/xor %ecx 1/r32/ecx
422 8a/byte-> *Keyboard-buffer:write 1/r32/cl
423 81 0/subop/add %ecx Keyboard-buffer:data/imm32
424
425 8a/byte-> *ecx 0/r32/al
426
427 3c/compare-al-and 0/imm8
428 0f 85/jump-if-!= $keyboard-interrupt-handler:end/disp32
429
430 e4/read-port-into-al 0x60/imm8
431
432
433 {
434 3c/compare-al-and 0xaa/imm8
435 75/jump-if-!= break/disp8
436
437 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
438 }
439
440 {
441 3c/compare-al-and 0xb6/imm8
442 75/jump-if-!= break/disp8
443
444 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
445 }
446
447 {
448 3c/compare-al-and 0x9d/imm8
449 75/jump-if-!= break/disp8
450
451 c7 0/subop/copy *Keyboard-ctrl-pressed? 0/imm32
452 }
453
454 50/push-eax
455 24/and-al-with 0x80/imm8
456 3c/compare-al-and 0/imm8
457 58/pop-to-eax
458 75/jump-if-!= $keyboard-interrupt-handler:end/disp8
459
460
461 {
462 3c/compare-al-and 0x2a/imm8
463 75/jump-if-!= break/disp8
464
465 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
466
467 eb/jump $keyboard-interrupt-handler:end/disp8
468 }
469
470 {
471 3c/compare-al-and 0x36/imm8
472 75/jump-if-!= break/disp8
473
474 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
475
476 eb/jump $keyboard-interrupt-handler:end/disp8
477 }
478
479 {
480 3c/compare-al-and 0x1d/imm8
481 75/jump-if-!= break/disp8
482
483 c7 0/subop/copy *Keyboard-ctrl-pressed? 1/imm32
484
485 eb/jump $keyboard-interrupt-handler:end/disp8
486 }
487
488
489 {
490 81 7/subop/compare *Keyboard-shift-pressed? 0/imm32
491 74/jump-if-= break/disp8
492
493 05/add-to-eax Keyboard-shift-map/imm32
494 8a/byte-> *eax 0/r32/al
495 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
496 }
497
498 {
499 81 7/subop/compare *Keyboard-ctrl-pressed? 0/imm32
500 74/jump-if-= break/disp8
501 05/add-to-eax Keyboard-ctrl-map/imm32
502 8a/byte-> *eax 0/r32/al
503 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
504 }
505
506 05/add-to-eax Keyboard-normal-map/imm32
507 8a/byte-> *eax 0/r32/al
508 $keyboard-interrupt-handler:select-map-done:
509
510 {
511 3c/compare-al-and 0/imm8
512 74/jump-if-= break/disp8
513
514 88/<- *ecx 0/r32/al
515
516 fe/increment-byte *Keyboard-buffer:write
517
518 80 4/subop/and-byte *Keyboard-buffer:write 0x0f/imm8
519 }
520 $keyboard-interrupt-handler:end:
521
522 9d/pop-flags
523 61/pop-all-registers
524 fb/enable-interrupts
525 cf/return-from-interrupt
526
527 == data
528 Keyboard-shift-pressed?:
529 0/imm32
530
531 Keyboard-ctrl-pressed?:
532 0/imm32
533
534
535 Keyboard-buffer:write:
536 0/imm32
537 Keyboard-buffer:read:
538 0/imm32
539 Keyboard-buffer:data:
540 00 00 00 00
541 00 00 00 00
542 00 00 00 00
543 00 00 00 00
544
545 +-- 95 lines: # Keyboard maps for translating keys to ASCII -----------------------------------------------------------------------------------------------------------------------------
640
641 Video-mode-info:
642 +-- 53 lines: # video mode info ---------------------------------------------------------------------------------------------------------------------------------------------------------
695
696
697
698
699
700
701
702
703
704
705 == data
706
707
708
709 Primary-bus-primary-drive:
710
711 0x1f7/imm32
712
713 0x1f7/imm32
714
715 0x3f6/imm32
716
717 0x1f1/imm32
718
719 0x1f6/imm32
720
721 0x1f2/imm32
722
723 0x1f3/imm32
724
725 0x1f4/imm32
726
727 0x1f5/imm32
728
729 0x1f0/imm32
730
731 0xe0/imm32
732
733
734
735 Primary-bus-secondary-drive:
736
737 0x1f7/imm32
738
739 0x1f7/imm32
740
741 0x3f6/imm32
742
743 0x1f1/imm32
744
745 0x1f6/imm32
746
747 0x1f2/imm32
748
749 0x1f3/imm32
750
751 0x1f4/imm32
752
753 0x1f5/imm32
754
755 0x1f0/imm32
756
757 0xf0/imm32
758
759 == code
760
761
762 read-ata-disk:
763
764 55/push-ebp
765 89/<- %ebp 4/r32/esp
766
767 50/push-eax
768 51/push-ecx
769 52/push-edx
770
771 81 7/subop/compare *(ebp+0x10) 0x100/imm32
772 {
773 7e/jump-if-<= break/disp8
774 (abort "read-ata-disk: no more than 0x100 sectors")
775 }
776
777 (drive-exists? *(ebp+8))
778 3d/compare-eax-and 0/imm32/false
779 0f 84/jump-if-= $read-ata-disk:end/disp32
780
781 (ata-drive-select *(ebp+8) *(ebp+0xc))
782 (clear-ata-error *(ebp+8))
783 (ata-sector-count *(ebp+8) *(ebp+0x10))
784 (ata-lba *(ebp+8) *(ebp+0xc))
785 (ata-command *(ebp+8) 0x20)
786
787 {
788
789
790
791 (while-ata-busy *(ebp+8))
792 (until-ata-data-available *(ebp+8))
793
794
795 8b/-> *(ebp+8) 0/r32/eax
796 8b/-> *(eax+0x24) 2/r32/edx
797
798 31/xor %eax 0/r32/eax
799 b9/copy-to-ecx 0x200/imm32
800 {
801 81 7/subop/compare %ecx 0/imm32
802 74/jump-if-= break/disp8
803 66 ed/read-port-dx-into-ax
804
805 (append-byte *(ebp+0x14) %eax)
806 49/decrement-ecx
807 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
808 (append-byte *(ebp+0x14) %eax)
809 49/decrement-ecx
810 eb/jump loop/disp8
811 }
812
813 ff 1/subop/decrement *(ebp+0x10)
814
815 81 7/subop/compare *(ebp+0x10) 0/imm32
816 7e/jump-if-<= break/disp8
817 (wait-400ns *(ebp+8))
818
819 e9/jump loop/disp32
820 }
821 $read-ata-disk:end:
822
823 5a/pop-to-edx
824 59/pop-to-ecx
825 58/pop-to-eax
826
827 89/<- %esp 5/r32/ebp
828 5d/pop-to-ebp
829 c3/return
830
831 write-ata-disk:
832
833 55/push-ebp
834 89/<- %ebp 4/r32/esp
835
836 50/push-eax
837 51/push-ecx
838 52/push-edx
839 53/push-ebx
840
841 (drive-exists? *(ebp+8))
842 3d/compare-eax-and 0/imm32/false
843 0f 84/jump-if-= $write-ata-disk:end/disp32
844
845 (ata-drive-select *(ebp+8) *(ebp+0xc))
846 (clear-ata-error *(ebp+8))
847 (ata-sector-count *(ebp+8) *(ebp+0x10))
848 (ata-lba *(ebp+8) *(ebp+0xc))
849 (ata-command *(ebp+8) 0x30)
850
851
852
853 {
854
855 (while-ata-busy *(ebp+8))
856 (until-ata-ready-for-data *(ebp+8))
857
858 8b/-> *(ebp+8) 0/r32/eax
859 8b/-> *(eax+0x24) 2/r32/edx
860
861 b9/copy-to-ecx 0x200/imm32
862
863
864 bb/copy-to-ebx 0xffff/imm32
865
866 $write-ata-disk:store-sector:
867 {
868 81 7/subop/compare %ecx 0/imm32
869 74/jump-if-= break/disp8
870
871 (stream-empty? *(ebp+0x14))
872 3d/compare-eax-and 0/imm32/false
873 75/jump-if-!= break/disp8
874
875 (read-byte *(ebp+0x14))
876
877 81 7/subop/compare %ebx 0xff/imm32
878 {
879 7e/jump-if-<= break/disp8
880 89/<- %ebx 0/r32/eax
881 eb/jump $write-ata-disk:store-sector/disp8
882 }
883
884 c1/shift 4/subop/left %eax 8/imm8
885 09/or %eax 3/r32/ebx
886 66 ef/write-ax-into-port-dx
887 49/decrement-ecx
888 49/decrement-ecx
889
890 bb/copy-to-ebx 0xffff/imm32
891 eb/jump loop/disp8
892 }
893
894
895 81 7/subop/compare %ebx 0xff/imm32
896 {
897 7f/jump-if-> break/disp8
898 89/<- %eax 3/r32/ebx
899 66 ef/write-ax-into-port-dx
900 49/decrement-ecx
901 49/decrement-ecx
902 }
903
904
905 31/xor %eax 0/r32/eax
906 {
907 81 7/subop/compare %ecx 0/imm32
908 74/jump-if-= break/disp8
909 66 ef/write-ax-into-port-dx
910 49/decrement-ecx
911 49/decrement-ecx
912 eb/jump loop/disp8
913 }
914
915
916 ff 1/subop/decrement *(ebp+0x10)
917 81 7/subop/compare *(ebp+0x10) 0/imm32
918 7e/jump-if-<= break/disp8
919
920 (wait-400ns *(ebp+8))
921
922 e9/jump loop/disp32
923 }
924
925 (flush-ata-cache *(ebp+8))
926
927 $write-ata-disk:end:
928
929 5b/pop-to-ebx
930 5a/pop-to-edx
931 59/pop-to-ecx
932 58/pop-to-eax
933
934 89/<- %esp 5/r32/ebp
935 5d/pop-to-ebp
936 c3/return
937
938 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237 read-mouse-event:
1238
1239 55/push-ebp
1240 89/<- %ebp 4/r32/esp
1241
1242 52/push-edx
1243 53/push-ebx
1244
1245 b8/copy-to-eax 0/imm32
1246 b9/copy-to-ecx 0/imm32
1247 (any-mouse-event?)
1248 3d/compare-eax-and 0/imm32/false
1249 74/jump-if-= $read-mouse-event:end/disp8
1250
1251 31/xor %eax 0/r32/eax
1252 e4/read-port-into-al 0x60/imm8
1253 89/<- %edx 0/r32/eax
1254 (wait-for-mouse-event)
1255
1256 31/xor %eax 0/r32/eax
1257 e4/read-port-into-al 0x60/imm8
1258 89/<- %ebx 0/r32/eax
1259 (wait-for-mouse-event)
1260
1261 31/xor %eax 0/r32/eax
1262 e4/read-port-into-al 0x60/imm8
1263 89/<- %ecx 0/r32/eax
1264
1265 89/<- %eax 3/r32/ebx
1266
1267 {
1268 f6 0/subop/test-bits %dl 0x10/imm8
1269 74/jump-if-zero break/disp8
1270 0d/or-eax-with 0xffffff00/imm32
1271 }
1272
1273 {
1274 f6 0/subop/test-bits %dl 0x20/imm8
1275 74/jump-if-zero break/disp8
1276 81 1/subop/or %ecx 0xffffff00/imm32
1277 }
1278 $read-mouse-event:end:
1279
1280 5b/pop-to-ebx
1281 5a/pop-to-edx
1282
1283 89/<- %esp 5/r32/ebp
1284 5d/pop-to-ebp
1285 c3/return
1286
1287 +--147 lines: # mouse helpers -----------------------------------------------------------------------------------------------------------------------------------------------------------
1434
1435