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 == code
23
24
25
26
27
28
29
30
31
32 fa/disable-interrupts
33
34
35 b8/copy-to-ax 0/imm16
36 8e/->seg 3/mod/direct 0/rm32/ax 3/r32/ds
37 8e/->seg 3/mod/direct 0/rm32/ax 0/r32/es
38 8e/->seg 3/mod/direct 0/rm32/ax 4/r32/fs
39 8e/->seg 3/mod/direct 0/rm32/ax 5/r32/gs
40
41
42
43
44
45 b8/copy-to-ax 0x7000/imm16
46 8e/->seg 3/mod/direct 0/rm32/ax 2/r32/ss
47 bc/copy-to-esp 0/imm16
48
49
50
51 {
52 e4/read-port-into-al 0x64/imm8
53 a8/test-bits-in-al 0x02/imm8
54 75/jump-if-!zero loop/imm8
55 b0/copy-to-al 0xd1/imm8
56 e6/write-al-into-port 0x64/imm8
57 }
58 {
59 e4/read-port-into-al 0x64/imm8
60 a8/test-bits-in-al 0x02/imm8
61 75/jump-if-!zero loop/imm8
62 b0/copy-to-al 0xdf/imm8
63 e6/write-al-into-port 0x64/imm8
64 }
65
66
67 b4/copy-to-ah 2/imm8/read-drive
68
69 b5/copy-to-ch 0/imm8/cylinder
70 b6/copy-to-dh 0/imm8/head
71 b1/copy-to-cl 2/imm8/sector
72 b0/copy-to-al 0x7d/imm8/num-sectors
73
74 bb/copy-to-bx 0/imm16
75 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
76 bb/copy-to-bx 0x7e00/imm16
77 cd/syscall 0x13/imm8/bios-disk-services
78 0f 82/jump-if-carry disk_error/disp16
79
80
81 b4/copy-to-ah 2/imm8/read-drive
82
83 b5/copy-to-ch 0/imm8/cylinder
84 b6/copy-to-dh 2/imm8/head
85 b1/copy-to-cl 1/imm8/sector
86 b0/copy-to-al 0x7e/imm8/num-sectors
87
88 bb/copy-to-bx 0x1780/imm16
89 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
90 bb/copy-to-bx 0/imm16
91 cd/syscall 0x13/imm8/bios-disk-services
92 0f 82/jump-if-carry disk_error/disp16
93
94
95 b4/copy-to-ah 2/imm8/read-drive
96
97 b5/copy-to-ch 0/imm8/cylinder
98 b6/copy-to-dh 4/imm8/head
99 b1/copy-to-cl 1/imm8/sector
100 b0/copy-to-al 0x7e/imm8/num-sectors
101
102 bb/copy-to-bx 0x2740/imm16
103 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
104 bb/copy-to-bx 0/imm16
105 cd/syscall 0x13/imm8/bios-disk-services
106 0f 82/jump-if-carry disk_error/disp16
107
108
109 bb/copy-to-bx 0/imm16
110 8e/->seg 3/mod/direct 3/rm32/bx 0/r32/es
111
112
113 b4/copy-to-ah 0x4f/imm8
114 b0/copy-to-al 2/imm8
115 bb/copy-to-bx 0x4105/imm16
116
117
118
119 cd/syscall 0x10/imm8/bios-video-services
120
121
122
123 b4/copy-to-ah 0x4f/imm8
124 b0/copy-to-al 1/imm8
125 b9/copy-to-cx 0x0105/imm16
126 bf/copy-to-di Video-mode-info/imm16
127 cd/syscall 0x10/imm8/bios-video-services
128
129
130
131
132
133
134 0f 01 2/subop/lgdt 0/mod/indirect 6/rm32/use-disp16 0x7cf8/disp16/gdt_descriptor
135
136 0f 20/<-cr 3/mod/direct 0/rm32/eax 0/r32/cr0
137 66 83 1/subop/or 3/mod/direct 0/rm32/eax 1/imm8
138 0f 22/->cr 3/mod/direct 0/rm32/eax 0/r32/cr0
139
140
141
142 ea/jump-far-absolute 0x00087d00/disp32
143
144 disk_error:
145
146
147 bb/copy-to-bx 0xb800/imm16
148 8e/->seg 3/mod/direct 3/rm32/bx 3/r32/ds
149 b0/copy-to-al 0x44/imm8/D
150 b4/copy-to-ah 0x0f/imm8/white-on-black
151 bb/copy-to-bx 0/imm16
152 89/<- 0/mod/indirect 7/rm32/bx 0/r32/ax
153
154 {
155 eb/jump loop/disp8
156 }
157
158
159 == data
160
161 gdt_start:
162
163 00 00 00 00 00 00 00 00
164
165 ff ff
166 00 00 00
167 9a
168
169 cf
170
171 00
172
173 ff ff
174 00 00 00
175 92
176
177 cf
178 00
179
180
181 == data 0x7cf8
182 gdt_descriptor:
183 0x17/imm16
184 gdt_start/imm32/start
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 0x8000/disp32/idt_descriptor
204
205
206
207
208
209
210
211
212
213
214
215 b0/copy-to-al 0xfd/imm8
216 e6/write-al-into-port 0x21/imm8
217
218 fb/enable-interrupts
219
220
221 db/floating-point-coprocessor e3/initialize
222
223 0f 20/<-cr 3/mod/direct 0/rm32/eax 4/r32/cr4
224
225 0f ba/bit-test 5/subop/bit-test-and-set 3/mod/direct 0/rm32/eax 9/imm8
226
227 0f 22/->cr 3/mod/direct 0/rm32/eax 4/r32/cr4
228
229 e9/jump Entry/disp32
230
231 == boot-sector-marker 0x7dfe
232
233 55 aa
234
235
236 == code
237
238 null-interrupt-handler:
239 cf/return-from-interrupt
240
241 keyboard-interrupt-handler:
242
243 fa/disable-interrupts
244 60/push-all-registers
245
246 b0/copy-to-al 0x20/imm8
247 e6/write-al-into-port 0x20/imm8
248 31/xor %eax 0/r32/eax
249
250 e4/read-port-into-al 0x64/imm8
251 a8/test-bits-in-al 0x01/imm8
252 74/jump-if-not-set $keyboard-interrupt-handler:epilogue/disp8
253
254
255 31/xor %ecx 1/r32/ecx
256 8a/byte-> *Keyboard-buffer:write 1/r32/cl
257 81 0/subop/add %ecx Keyboard-buffer:data/imm32
258
259 8a/byte-> *ecx 0/r32/al
260
261 3c/compare-al-and 0/imm8
262 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
263
264 e4/read-port-into-al 0x60/imm8
265
266
267 {
268 3c/compare-al-and 0xaa/imm8
269 75/jump-if-!= break/disp8
270
271 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
272 }
273
274 {
275 3c/compare-al-and 0xb6/imm8
276 75/jump-if-!= break/disp8
277
278 c7 0/subop/copy *Keyboard-shift-pressed? 0/imm32
279 }
280
281 {
282 3c/compare-al-and 0x9d/imm8
283 75/jump-if-!= break/disp8
284
285 c7 0/subop/copy *Keyboard-ctrl-pressed? 0/imm32
286 }
287
288 50/push-eax
289 24/and-al-with 0x80/imm8
290 3c/compare-al-and 0/imm8
291 58/pop-to-eax
292 75/jump-if-!= $keyboard-interrupt-handler:epilogue/disp8
293
294
295 {
296 3c/compare-al-and 0x2a/imm8
297 75/jump-if-!= break/disp8
298
299 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
300
301 eb/jump $keyboard-interrupt-handler:epilogue/disp8
302 }
303
304 {
305 3c/compare-al-and 0x36/imm8
306 75/jump-if-!= break/disp8
307
308 c7 0/subop/copy *Keyboard-shift-pressed? 1/imm32
309
310 eb/jump $keyboard-interrupt-handler:epilogue/disp8
311 }
312
313 {
314 3c/compare-al-and 0x1d/imm8
315 75/jump-if-!= break/disp8
316
317 c7 0/subop/copy *Keyboard-ctrl-pressed? 1/imm32
318
319 eb/jump $keyboard-interrupt-handler:epilogue/disp8
320 }
321
322
323 {
324 81 7/subop/compare *Keyboard-shift-pressed? 0/imm32
325 74/jump-if-= break/disp8
326
327 05/add-to-eax Keyboard-shift-map/imm32
328 8a/byte-> *eax 0/r32/al
329 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
330 }
331
332 {
333 81 7/subop/compare *Keyboard-ctrl-pressed? 0/imm32
334 74/jump-if-= break/disp8
335 05/add-to-eax Keyboard-ctrl-map/imm32
336 8a/byte-> *eax 0/r32/al
337 eb/jump $keyboard-interrupt-handler:select-map-done/disp8
338 }
339
340 05/add-to-eax Keyboard-normal-map/imm32
341 8a/byte-> *eax 0/r32/al
342 $keyboard-interrupt-handler:select-map-done:
343
344 {
345 3c/compare-al-and 0/imm8
346 74/jump-if-= break/disp8
347
348 88/<- *ecx 0/r32/al
349
350 fe/increment-byte *Keyboard-buffer:write
351
352 80 4/subop/and-byte *Keyboard-buffer:write 0x0f/imm8
353 }
354 $keyboard-interrupt-handler:epilogue:
355
356 61/pop-all-registers
357 fb/enable-interrupts
358 cf/return-from-interrupt
359
360
361
362 == data 0x8000
363 idt_descriptor:
364 ff 03
365 idt_start/imm32/start
366
367 Keyboard-shift-pressed?:
368 0/imm32
369
370 Keyboard-ctrl-pressed?:
371 0/imm32
372
373
374 Keyboard-buffer:write:
375 0/imm32
376 Keyboard-buffer:read:
377 0/imm32
378 Keyboard-buffer:data:
379 00 00 00 00
380 00 00 00 00
381 00 00 00 00
382 00 00 00 00
383
384 == data 0x8100
385 Video-mode-info:
386 +-- 53 lines: # video mode info ---------------------------------------------------------------------------------------------------------------------------------------------------------
439
440 == data 0x8200
441 +--161 lines: # interrupt descriptor table ----------------------------------------------------------------------------------------------------------------------------------------------
602
603 == data 0x8600
604 +-- 72 lines: # translating keys to ASCII -----------------------------------------------------------------------------------------------------------------------------------------------
676
677 == data 0x8c00
678 Font:
679 +--236 lines: # Bitmaps for some ASCII characters (soon Unicode) ------------------------------------------------------------------------------------------------------------------------
915
916
917 == code 0x9400
918
919
920
921
922
923
924
925
926
927 load-first-sector-from-primary-bus-secondary-drive:
928
929 55/push-ebp
930 89/<- %ebp 4/r32/esp
931
932 50/push-eax
933 51/push-ecx
934 52/push-edx
935
936 (secondary-drive-exists?)
937 3d/compare-eax-and 0/imm32/false
938 0f 84/jump-if-= $load-first-sector-from-primary-bus-secondary-drive:end/disp32
939
940 (ata-drive-select 0xf0)
941 (clear-ata-error)
942 (ata-sector-count 1)
943 (ata-lba 0 0 0)
944 (ata-command 0x20)
945
946 (while-ata-busy)
947 (until-ata-data-available)
948
949 31/xor %eax 0/r32/eax
950 ba/copy-to-edx 0x1f0/imm32
951 b9/copy-to-ecx 0x200/imm32
952 {
953 81 7/subop/compare %ecx 0/imm32
954 74/jump-if-= break/disp8
955 66 ed/read-port-dx-into-ax
956
957 (append-byte *(ebp+8) %eax)
958 49/decrement-ecx
959 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
960 (append-byte *(ebp+8) %eax)
961 49/decrement-ecx
962 eb/jump loop/disp8
963 }
964 $load-first-sector-from-primary-bus-secondary-drive:end:
965
966 5a/pop-to-edx
967 59/pop-to-ecx
968 58/pop-to-eax
969
970 89/<- %esp 5/r32/ebp
971 5d/pop-to-ebp
972 c3/return
973
974 store-first-sector-to-primary-bus-secondary-drive:
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 53/push-ebx
983
984 (secondary-drive-exists?)
985 3d/compare-eax-and 0/imm32/false
986 0f 84/jump-if-= $store-first-sector-to-primary-bus-secondary-drive:end/disp32
987
988 (ata-drive-select 0xf0)
989 (clear-ata-error)
990 (ata-sector-count 1)
991 (ata-lba 0 0 0)
992 (ata-command 0x30)
993
994 (while-ata-busy)
995 (until-ata-ready-for-data)
996
997 ba/copy-to-edx 0x1f0/imm32
998 b9/copy-to-ecx 0x200/imm32
999
1000
1001 bb/copy-to-ebx 0xffff/imm32
1002 $store-first-sector-to-primary-bus-secondary-drive:loop:
1003 {
1004 81 7/subop/compare %ecx 0/imm32
1005 74/jump-if-= break/disp8
1006
1007 (stream-empty? *(ebp+8))
1008 3d/compare-eax-and 0/imm32/false
1009 75/jump-if-!= break/disp8
1010
1011 (read-byte *(ebp+8))
1012
1013 81 7/subop/compare %ebx 0xff/imm32
1014 {
1015 7e/jump-if-<= break/disp8
1016 89/<- %ebx 0/r32/eax
1017 eb/jump $store-first-sector-to-primary-bus-secondary-drive:loop/disp8
1018 }
1019
1020 c1/shift 4/subop/left %eax 8/imm8
1021 09/or %eax 3/r32/ebx
1022 66 ef/write-ax-into-port-dx
1023 49/decrement-ecx
1024 49/decrement-ecx
1025
1026 bb/copy-to-ebx 0xffff/imm32
1027 eb/jump loop/disp8
1028 }
1029
1030 81 7/subop/compare %ebx 0xff/imm32
1031 {
1032 7f/jump-if-> break/disp8
1033 89/<- %eax 3/r32/ebx
1034 66 ef/write-ax-into-port-dx
1035 49/decrement-ecx
1036 49/decrement-ecx
1037 }
1038
1039 31/xor %eax 0/r32/eax
1040 {
1041 81 7/subop/compare %ecx 0/imm32
1042 74/jump-if-= break/disp8
1043 66 ef/write-ax-into-port-dx
1044 49/decrement-ecx
1045 49/decrement-ecx
1046 eb/jump loop/disp8
1047 }
1048 $store-first-sector-to-primary-bus-secondary-drive:end:
1049
1050 5b/pop-to-ebx
1051 5a/pop-to-edx
1052 59/pop-to-ecx
1053 58/pop-to-eax
1054
1055 89/<- %esp 5/r32/ebp
1056 5d/pop-to-ebp
1057 c3/return
1058
1059 secondary-drive-exists?:
1060
1061 55/push-ebp
1062 89/<- %ebp 4/r32/esp
1063
1064 52/push-edx
1065
1066 {
1067 31/xor %eax 0/r32/eax
1068 ba/copy-to-edx 0x1f7/imm32
1069 ec/read-port-dx-into-al
1070 3d/compare-eax-and 0xff/imm32
1071
1072 b8/copy-to-eax 0/imm32/false
1073 74/jump-if-= $secondary-drive-exists?:end/disp8
1074 }
1075
1076 (ata-drive-select 0xb0)
1077 (ata-sector-count 0)
1078 (ata-lba 0 0 0)
1079 (ata-command 0xec)
1080
1081
1082 31/xor %eax 0/r32/eax
1083 ba/copy-to-edx 0x1f7/imm32
1084 ec/read-port-dx-into-al
1085
1086 3d/compare-eax-and 0/imm32
1087 {
1088 74/jump-if-= break/disp8
1089 b8/copy-to-eax 1/imm32/true
1090 eb/jump $secondary-drive-exists?:complete-identify/disp8
1091 }
1092
1093 b8/copy-to-eax 0/imm32/false
1094 $secondary-drive-exists?:complete-identify:
1095 50/push-eax
1096
1097 ba/copy-to-edx 0x1f0/imm32
1098 b9/copy-to-ecx 0x200/imm32
1099 {
1100 81 7/subop/compare %ecx 0/imm32
1101 74/jump-if-= break/disp8
1102
1103 ed/read-port-dx-into-eax
1104 49/decrement-ecx
1105 49/decrement-ecx
1106 49/decrement-ecx
1107 49/decrement-ecx
1108 eb/jump loop/disp8
1109 }
1110 58/pop-to-eax
1111 $secondary-drive-exists?:end:
1112
1113 5a/pop-to-edx
1114
1115 89/<- %esp 5/r32/ebp
1116 5d/pop-to-ebp
1117 c3/return
1118
1119 ata-drive-select:
1120
1121 55/push-ebp
1122 89/<- %ebp 4/r32/esp
1123
1124 50/push-eax
1125 52/push-edx
1126
1127 8b/-> *(ebp+8) 0/r32/eax
1128 ba/copy-to-edx 0x1f6/imm32
1129 ee/write-al-into-port-dx
1130 $ata-drive-select:end:
1131
1132 5a/pop-to-edx
1133 58/pop-to-eax
1134
1135 89/<- %esp 5/r32/ebp
1136 5d/pop-to-ebp
1137 c3/return
1138
1139 clear-ata-error:
1140
1141 55/push-ebp
1142 89/<- %ebp 4/r32/esp
1143
1144 50/push-eax
1145 52/push-edx
1146
1147 b8/copy-to-eax 0/imm32
1148 ba/copy-to-edx 0x1f1/imm32
1149 ee/write-al-into-port-dx
1150 $ata-error:end:
1151
1152 5a/pop-to-edx
1153 58/pop-to-eax
1154
1155 89/<- %esp 5/r32/ebp
1156 5d/pop-to-ebp
1157 c3/return
1158
1159 ata-sector-count:
1160
1161 55/push-ebp
1162 89/<- %ebp 4/r32/esp
1163
1164 50/push-eax
1165 52/push-edx
1166
1167 8b/-> *(ebp+8) 0/r32/eax
1168 ba/copy-to-edx 0x1f2/imm32
1169 ee/write-al-into-port-dx
1170 $ata-sector-count:end:
1171
1172 5a/pop-to-edx
1173 58/pop-to-eax
1174
1175 89/<- %esp 5/r32/ebp
1176 5d/pop-to-ebp
1177 c3/return
1178
1179 ata-lba:
1180
1181 55/push-ebp
1182 89/<- %ebp 4/r32/esp
1183
1184 50/push-eax
1185 52/push-edx
1186
1187 8b/-> *(ebp+8) 0/r32/eax
1188 ba/copy-to-edx 0x1f3/imm32
1189 ee/write-al-into-port-dx
1190
1191 8b/-> *(ebp+0xc) 0/r32/eax
1192 ba/copy-to-edx 0x1f4/imm32
1193 ee/write-al-into-port-dx
1194
1195 8b/-> *(ebp+0x10) 0/r32/eax
1196 ba/copy-to-edx 0x1f5/imm32
1197 ee/write-al-into-port-dx
1198 $ata-lba:end:
1199
1200 5a/pop-to-edx
1201 58/pop-to-eax
1202
1203 89/<- %esp 5/r32/ebp
1204 5d/pop-to-ebp
1205 c3/return
1206
1207
1208
1209 ata-cyl-sector:
1210
1211 55/push-ebp
1212 89/<- %ebp 4/r32/esp
1213
1214 50/push-eax
1215 52/push-edx
1216
1217 8b/-> *(ebp+8) 0/r32/eax
1218 ba/copy-to-edx 0x1f3/imm32
1219 ee/write-al-into-port-dx
1220
1221 8b/-> *(ebp+0xc) 0/r32/eax
1222 ba/copy-to-edx 0x1f4/imm32
1223 ee/write-al-into-port-dx
1224
1225 8b/-> *(ebp+0x10) 0/r32/eax
1226 ba/copy-to-edx 0x1f5/imm32
1227 ee/write-al-into-port-dx
1228 $ata-lba:end:
1229
1230 5a/pop-to-edx
1231 58/pop-to-eax
1232
1233 89/<- %esp 5/r32/ebp
1234 5d/pop-to-ebp
1235 c3/return
1236
1237 ata-command:
1238
1239 55/push-ebp
1240 89/<- %ebp 4/r32/esp
1241
1242 50/push-eax
1243 52/push-edx
1244
1245 8b/-> *(ebp+8) 0/r32/eax
1246 ba/copy-to-edx 0x1f7/imm32
1247 ee/write-al-into-port-dx
1248 $ata-command:end:
1249
1250 5a/pop-to-edx
1251 58/pop-to-eax
1252
1253 89/<- %esp 5/r32/ebp
1254 5d/pop-to-ebp
1255 c3/return
1256
1257 while-ata-busy:
1258
1259 50/push-eax
1260 52/push-edx
1261
1262 ba/copy-to-edx 0x1f7/imm32
1263 {
1264 ec/read-port-dx-into-al
1265 a8/test-bits-in-al 0x80/imm8/bsy
1266 75/jump-if-zf-not-set-and-bit-7-set loop/disp8
1267 }
1268 $while-ata-busy:end:
1269
1270 5a/pop-to-edx
1271 58/pop-to-eax
1272
1273 c3/return
1274
1275 until-ata-data-available:
1276
1277 50/push-eax
1278 52/push-edx
1279
1280 ba/copy-to-edx 0x1f7/imm32
1281 {
1282 ec/read-port-dx-into-al
1283 a8/test-bits-in-al 8/imm8/drq
1284 74/jump-if-zf-set-and-bit-3-not-set loop/disp8
1285 }
1286 $while-ata-busy:end:
1287
1288 5a/pop-to-edx
1289 58/pop-to-eax
1290
1291 c3/return
1292
1293 until-ata-ready-for-data:
1294 (until-ata-data-available)
1295 c3/return
1296
1297