From 7bf8adb893dcc524c7f1bc5e8f984385c9138d7d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 27 Mar 2021 17:47:23 -0700 Subject: [PATCH] explicitly pass data disk to main --- 400.mu | 4 +- boot.subx | 395 ++++++++++++++++++++++++++++++++++++++------------- ex10.mu | 2 +- ex2.mu | 2 +- ex3.mu | 2 +- ex4.mu | 2 +- ex5.mu | 2 +- ex6.mu | 2 +- ex7.mu | 2 +- ex8.mu | 2 +- ex9.mu | 6 +- life.mu | 2 +- mu-init.subx | 4 +- mu.md | 5 +- rpn.mu | 2 +- 15 files changed, 316 insertions(+), 118 deletions(-) diff --git a/400.mu b/400.mu index 2cf3c126..7bef992a 100644 --- a/400.mu +++ b/400.mu @@ -9,8 +9,8 @@ sig draw-cursor-on-real-screen g: grapheme sig read-key kbd: (addr keyboard) -> _/eax: byte # disk -sig load-first-sector-from-primary-bus-secondary-drive out: (addr stream byte) -sig store-first-sector-to-primary-bus-secondary-drive out: (addr stream byte) +sig load-sector disk: (addr disk), lba: int, out: (addr stream byte) +sig store-sector disk: (addr disk), lba: int, out: (addr stream byte) # mouse sig read-mouse-event -> _/eax: int, _/ecx: int diff --git a/boot.subx b/boot.subx index bc49b49d..8a4a5595 100644 --- a/boot.subx +++ b/boot.subx @@ -814,7 +814,42 @@ Font: # https://forum.osdev.org/viewtopic.php?f=1&p=167798 # read-sector, according to https://www.scs.stanford.edu/11wi-cs140/pintos/specs/ata-3-std.pdf -load-first-sector-from-primary-bus-secondary-drive: # out: (addr stream byte) +== data + +# We'll be gaining access just to the secondary drive on the primary bus for +# now. It will have the designated 'data' disk so we don't mess with the code +# disk. +# +# The type definition for this variable is in safe Mu (rather than unsafe +# SubX) code. +# All ports are 8-bit except data-port, which is 16-bit. +Primary-bus-secondary-drive: + # command-port: int (write) + 0x1f7/imm32 + # status-port: int (read) + 0x1f7/imm32 + # alternative-status-port: int (read) + 0x3f6/imm32 + # error-port: int (read) + 0x1f1/imm32 + # drive-and-head-port: int + 0x1f6/imm32 + # sector-count-port: int + 0x1f2/imm32 + # lba-low-port: int + 0x1f3/imm32 + # lba-mid-port: int + 0x1f4/imm32 + # lba-high-port: int + 0x1f5/imm32 + # data-port: int + 0x1f0/imm32 + # drive-code: byte # only drive-specific field + 0xf0/imm32 # LBA mode also enabled + +== code + +load-sector: # disk: (addr disk), lba: int, out: (addr stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -823,35 +858,46 @@ load-first-sector-from-primary-bus-secondary-drive: # out: (addr stream byte) 51/push-ecx 52/push-edx # check for drive - (secondary-drive-exists?) # => eax + (drive-exists? *(ebp+8)) # => eax 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $load-first-sector-from-primary-bus-secondary-drive:end/disp32 + 0f 84/jump-if-= $load-sector:end/disp32 # kick off read - (ata-drive-select 0xf0) # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0) - (clear-ata-error) - (ata-sector-count 1) - (ata-lba 0 0 0) # lower 24 bits of LBA, all 0 - (ata-command 0x20) # read sectors with retries + (ata-drive-select *(ebp+8) *(ebp+0xc)) + (clear-ata-error *(ebp+8)) + (ata-sector-count *(ebp+8) 1) + (ata-lba *(ebp+8) *(ebp+0xc)) + (ata-command *(ebp+8) 0x20) # read sectors with retries # poll for results - (while-ata-busy) - (until-ata-data-available) + (while-ata-busy *(ebp+8)) + (until-ata-data-available *(ebp+8)) + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "A: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } # emit results 31/xor %eax 0/r32/eax - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 66 ed/read-port-dx-into-ax # write 2 bytes to stream one at a time - (append-byte *(ebp+8) %eax) + (append-byte *(ebp+0x10) %eax) 49/decrement-ecx c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 - (append-byte *(ebp+8) %eax) + (append-byte *(ebp+0x10) %eax) 49/decrement-ecx eb/jump loop/disp8 } -$load-first-sector-from-primary-bus-secondary-drive:end: +$load-sector:end: # . restore registers 5a/pop-to-edx 59/pop-to-ecx @@ -861,7 +907,7 @@ $load-first-sector-from-primary-bus-secondary-drive:end: 5d/pop-to-ebp c3/return -store-first-sector-to-primary-bus-secondary-drive: # in: (addr stream byte) +store-sector: # disk: (addr disk), lba: int, in: (addr stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -871,40 +917,42 @@ store-first-sector-to-primary-bus-secondary-drive: # in: (addr stream byte) 52/push-edx 53/push-ebx # check for drive - (secondary-drive-exists?) # => eax + (drive-exists? *(ebp+8)) # => eax 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $store-first-sector-to-primary-bus-secondary-drive:end/disp32 + 0f 84/jump-if-= $store-sector:end/disp32 # kick off write - (ata-drive-select 0xf0) # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0) - (clear-ata-error) - (ata-sector-count 1) - (ata-lba 0 0 0) # lower 24 bits of LBA, all 0 - (ata-command 0x30) # write sectors with retries + (ata-drive-select *(ebp+8) *(ebp+0xc)) + (clear-ata-error *(ebp+8)) + (ata-sector-count *(ebp+8) 1) + (ata-lba *(ebp+8) *(ebp+0xc)) + (ata-command *(ebp+8) 0x30) # write sectors with retries # wait - (while-ata-busy) - (until-ata-ready-for-data) + (while-ata-busy *(ebp+8)) + (until-ata-ready-for-data *(ebp+8)) + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx # send data - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector - # var first-byte/ebx: byte - # when it's more than 0xff, we're at an even-numbered byte + # . var first-byte/ebx: byte + # . when it's more than 0xff, we're at an even-numbered byte bb/copy-to-ebx 0xffff/imm32 -$store-first-sector-to-primary-bus-secondary-drive:loop: +$store-sector:loop: { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 # this loop is slow, but the ATA spec also requires a small delay - (stream-empty? *(ebp+8)) # => eax + (stream-empty? *(ebp+0x10)) # => eax 3d/compare-eax-and 0/imm32/false 75/jump-if-!= break/disp8 # read byte from stream - (read-byte *(ebp+8)) # => eax + (read-byte *(ebp+0x10)) # => eax # if we're at an odd-numbered byte, save it to first-byte 81 7/subop/compare %ebx 0xff/imm32 { 7e/jump-if-<= break/disp8 89/<- %ebx 0/r32/eax - eb/jump $store-first-sector-to-primary-bus-secondary-drive:loop/disp8 + eb/jump $store-sector:loop/disp8 } # otherwise OR it with first-byte and write it out c1/shift 4/subop/left %eax 8/imm8 @@ -935,7 +983,7 @@ $store-first-sector-to-primary-bus-secondary-drive:loop: 49/decrement-ecx eb/jump loop/disp8 } -$store-first-sector-to-primary-bus-secondary-drive:end: +$store-sector:end: # . restore registers 5b/pop-to-ebx 5a/pop-to-edx @@ -948,7 +996,7 @@ $store-first-sector-to-primary-bus-secondary-drive:end: # disk helpers {{{ -secondary-drive-exists?: # -> _/eax: boolean +drive-exists?: # disk: (addr disk) -> _/eax: boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -958,36 +1006,68 @@ secondary-drive-exists?: # -> _/eax: boolean { 31/xor %eax 0/r32/eax ba/copy-to-edx 0x1f7/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "B: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ec/read-port-dx-into-al 3d/compare-eax-and 0xff/imm32 # if eax is 0xff, primary bus has no drives b8/copy-to-eax 0/imm32/false - 74/jump-if-= $secondary-drive-exists?:end/disp8 + 74/jump-if-= $drive-exists?:end/disp8 } # identify - (ata-drive-select 0xf0) # primary bus, secondary drive - (ata-sector-count 0) - (ata-lba 0 0 0) - (ata-command 0xec) # identify - # read status register + (ata-drive-select *(ebp+8) 0) + (ata-sector-count *(ebp+8) 0) + (ata-lba *(ebp+8) 0) + (ata-command *(ebp+8) 0xec) # identify + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + # read status port # TODO: might need to spin here for 400ns: https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#400ns_delays 31/xor %eax 0/r32/eax - ba/copy-to-edx 0x1f7/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "C: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ec/read-port-dx-into-al - # if eax is 0, secondary drive does not exist + # if eax is 0, drive does not exist 3d/compare-eax-and 0/imm32 { 74/jump-if-= break/disp8 b8/copy-to-eax 1/imm32/true - eb/jump $secondary-drive-exists?:complete-identify/disp8 + eb/jump $drive-exists?:complete-identify/disp8 } # TODO: might need to perform remaining steps at https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#IDENTIFY_command b8/copy-to-eax 0/imm32/false -$secondary-drive-exists?:complete-identify: +$drive-exists?:complete-identify: 50/push-eax + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx # 0x24 = data-port offset # clear FIFO from the drive - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "D: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 @@ -1000,7 +1080,7 @@ $secondary-drive-exists?:complete-identify: eb/jump loop/disp8 } 58/pop-to-eax -$secondary-drive-exists?:end: +$drive-exists?:end: # . restore registers 5a/pop-to-edx # . epilogue @@ -1008,19 +1088,45 @@ $secondary-drive-exists?:end: 5d/pop-to-ebp c3/return -ata-drive-select: # n: byte +ata-drive-select: # disk: (addr disk), lba: int # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # - 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f6/imm32 + 56/push-esi + # esi = disk + 8b/-> *(ebp+8) 6/r32/esi + # var drive-head/edx: byte = lba >> 24 + 8b/-> *(ebp+0xc) 2/r32/edx + c1/shift 5/subop/right-padding-zeroes %edx 0x18/imm8 + # var drive-code/eax: byte = disk->drive-code | drive-head + 8b/-> *(esi+0x28) 0/r32/eax # 0x28 = drive-code offset + 09/or= %eax 2/r32/edx + # var drive-and-head-port/edx: int + 8b/-> *(esi+0x10) 2/r32/edx # 0x10 = drive-and-head-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "E: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-drive-select:end: # . restore registers + 5e/pop-to-esi 5a/pop-to-edx 58/pop-to-eax # . epilogue @@ -1028,16 +1134,35 @@ $ata-drive-select:end: 5d/pop-to-ebp c3/return -clear-ata-error: +clear-ata-error: # disk: (addr disk) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx + # var error-port/edx = disk->error-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0xc) 2/r32/edx # 0xc = error-port offset # b8/copy-to-eax 0/imm32 - ba/copy-to-edx 0x1f1/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "F: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-error:end: # . restore registers @@ -1048,16 +1173,35 @@ $ata-error:end: 5d/pop-to-ebp c3/return -ata-sector-count: # n: byte +ata-sector-count: # disk: (addr disk), n: byte # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # + # var sector-count-port/edx = disk->sector-count-port 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f2/imm32 + 8b/-> *(eax+0x14) 2/r32/edx # 0x14 = sector-count-port offset + # + 8b/-> *(ebp+0xc) 0/r32/eax + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "G: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-sector-count:end: # . restore registers @@ -1068,24 +1212,68 @@ $ata-sector-count:end: 5d/pop-to-ebp c3/return -ata-lba: # lo: byte, mid: byte, hi: byte +ata-lba: # disk: (addr disk), lba: int # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # lo + # var port/edx = disk->port 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f3/imm32 + 8b/-> *(eax+0x18) 2/r32/edx # 0x18 = lba-low-port offset + # eax = lba + 8b/-> *(ebp+0xc) 0/r32/eax + # lo + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "H: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx # mid - 8b/-> *(ebp+0xc) 0/r32/eax - ba/copy-to-edx 0x1f4/imm32 + 42/increment-dx # lba-mid-port + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + { + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "I: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + } ee/write-al-into-port-dx # hi - 8b/-> *(ebp+0x10) 0/r32/eax - ba/copy-to-edx 0x1f5/imm32 + 42/increment-dx # lba-high-port + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "J: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-lba:end: # . restore registers @@ -1096,46 +1284,35 @@ $ata-lba:end: 5d/pop-to-ebp c3/return -# sector: [1, 63] -# cylinder: [0, 1023] -ata-cyl-sector: # sector: byte, cyl-lo: byte, cyl-hi: byte +ata-command: # disk: (addr disk), cmd: byte # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # sector + # var command-port/edx = disk->command-port 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f3/imm32 - ee/write-al-into-port-dx - # cyl-lo - 8b/-> *(ebp+0xc) 0/r32/eax - ba/copy-to-edx 0x1f4/imm32 - ee/write-al-into-port-dx - # cyl-hi - 8b/-> *(ebp+0x10) 0/r32/eax - ba/copy-to-edx 0x1f5/imm32 - ee/write-al-into-port-dx -$ata-lba:end: - # . restore registers - 5a/pop-to-edx - 58/pop-to-eax - # . epilogue - 89/<- %esp 5/r32/ebp - 5d/pop-to-ebp - c3/return - -ata-command: # cmd: byte - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # . save registers - 50/push-eax - 52/push-edx + 8b/-> *(eax+0) 2/r32/edx # 0 = command-port offset # - 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f7/imm32 + 8b/-> *(ebp+0xc) 0/r32/eax + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "K: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-command:end: # . restore registers @@ -1146,12 +1323,22 @@ $ata-command:end: 5d/pop-to-ebp c3/return -while-ata-busy: +while-ata-busy: # disk: (addr disk) # . save registers 50/push-eax 52/push-edx - # - ba/copy-to-edx 0x1f7/imm32 + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "L: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } { ec/read-port-dx-into-al a8/test-bits-in-al 0x80/imm8/bsy # set zf if bit 7 (most significant) is not set @@ -1164,12 +1351,22 @@ $while-ata-busy:end: # . epilogue c3/return -until-ata-data-available: +until-ata-data-available: # disk: (addr disk) # . save registers 50/push-eax 52/push-edx - # - ba/copy-to-edx 0x1f7/imm32 + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "M: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } { ec/read-port-dx-into-al a8/test-bits-in-al 8/imm8/drq # set zf if bit 3 is not set diff --git a/ex10.mu b/ex10.mu index 4d30ac70..608fdcec 100644 --- a/ex10.mu +++ b/ex10.mu @@ -11,7 +11,7 @@ # Values between -256 and +255 as you move the mouse over the window. # You might need to click on the window once. -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { # repeatedly print out mouse driver results if non-zero $main:event-loop: { var dx/eax: int <- copy 0 diff --git a/ex2.mu b/ex2.mu index e47b3add..f595510c 100644 --- a/ex2.mu +++ b/ex2.mu @@ -7,7 +7,7 @@ # Or: # bochs -f bochsrc # bochsrc loads disk.img -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var y/eax: int <- copy 0 { compare y, 0x300/screen-height=768 diff --git a/ex3.mu b/ex3.mu index b4014dbd..bf4af1d9 100644 --- a/ex3.mu +++ b/ex3.mu @@ -11,7 +11,7 @@ # Expected output: a new green pixel starting from the top left corner of the # screen every time you press a key (letter or digit) -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var x/ecx: int <- copy 0 var y/edx: int <- copy 0 { diff --git a/ex4.mu b/ex4.mu index 77a89f81..caed4e5c 100644 --- a/ex4.mu +++ b/ex4.mu @@ -9,6 +9,6 @@ # # Expected output: letter 'A' in green near the top-left corner of screen -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { draw-code-point screen, 0x41/A, 2/row, 1/col, 0xa/fg, 0/bg } diff --git a/ex5.mu b/ex5.mu index 90bcac2f..6f776d16 100644 --- a/ex5.mu +++ b/ex5.mu @@ -10,7 +10,7 @@ # # Expected output: text in green near the top-left corner of screen -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var dummy/eax: int <- draw-text-rightward screen, "hello from baremetal Mu!", 0x10/x, 0x400/xmax, 0x10/y, 0xa/fg, 0/bg dummy <- draw-text-rightward screen, "you shouldn't see this", 0x10/x, 0xa0/xmax, 0x30/y, 3/fg, 0/bg # xmax is too narrow } diff --git a/ex6.mu b/ex6.mu index 64607678..16aa34eb 100644 --- a/ex6.mu +++ b/ex6.mu @@ -9,7 +9,7 @@ # # Expected output: a box and text that doesn't overflow it -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { # drawing text within a bounding box draw-box-on-real-screen 0xf, 0x1f, 0x79, 0x51, 0x4 var x/eax: int <- copy 0x20 diff --git a/ex7.mu b/ex7.mu index 0b84d584..ea4bf6aa 100644 --- a/ex7.mu +++ b/ex7.mu @@ -10,7 +10,7 @@ # Expected output: an interactive game a bit like "snakes". Try pressing h, j, # k, l. -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var space/eax: grapheme <- copy 0x20 set-cursor-position screen, 0, 0 { diff --git a/ex8.mu b/ex8.mu index 1be5dfc9..4d7e2836 100644 --- a/ex8.mu +++ b/ex8.mu @@ -6,7 +6,7 @@ # bochs -f bochsrc # bochsrc loads disk.img # Set a breakpoint at 0x7c00 and start stepping. -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var n/eax: int <- copy 0 var result/xmm0: float <- convert n } diff --git a/ex9.mu b/ex9.mu index 003eeb4c..dc5dffd0 100644 --- a/ex9.mu +++ b/ex9.mu @@ -15,17 +15,17 @@ # 6. Notice that the data disk now contains the word count of the original text. # xxd data.img |head -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var text-storage: (stream byte 0x200) var text/esi: (addr stream byte) <- address text-storage - load-first-sector-from-primary-bus-secondary-drive text + load-sector data-disk, 0/lba, text var word-count/eax: int <- word-count text var result-storage: (stream byte 0x10) var result/edi: (addr stream byte) <- address result-storage write-int32-decimal result, word-count - store-first-sector-to-primary-bus-secondary-drive result + store-sector data-disk, 0/lba, result } fn word-count in: (addr stream byte) -> _/eax: int { diff --git a/life.mu b/life.mu index af69c589..829443b7 100644 --- a/life.mu +++ b/life.mu @@ -211,7 +211,7 @@ fn render grid: (addr array boolean) { } } -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { #? # allocate on the stack #? var grid1-storage: (array boolean 0xc000) # width * height #? var grid1/esi: (addr array boolean) <- address grid1-storage diff --git a/mu-init.subx b/mu-init.subx index 399a9a3f..08a8856e 100644 --- a/mu-init.subx +++ b/mu-init.subx @@ -3,7 +3,7 @@ # See translate for how this file is used. # # Mu programs start at a function called 'main' with this signature: -# fn main screen: (addr screen), keyboard: (addr keyboard) +# fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) # # All tests must pass first (the "power-on unit test"). @@ -22,7 +22,7 @@ Entry: (clear-real-screen) c7 0/subop/copy *Real-screen-cursor-x 0/imm32 c7 0/subop/copy *Real-screen-cursor-y 0/imm32 - (main 0 0) + (main 0 0 Primary-bus-secondary-drive) } # hang indefinitely diff --git a/mu.md b/mu.md index 09856068..dc6d9ff0 100644 --- a/mu.md +++ b/mu.md @@ -117,15 +117,16 @@ It takes an array of strings and returns a status code to Linux in register Without an OS, the signature looks like this: ``` -fn main screen: (addr screen), keyboard: (addr keyboard) +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) ``` A screen and keyboard are explicitly passed in. The goal is for all hardware dependencies to always be explicit. However there are currently gaps: * The mouse is accessed implicitly - * The disk is accessed implicitly * The screen argument only supports text-mode graphics. Pixel graphics rely on implicit access to the screen. + * The Mu computer has two disks, and the disk containing Mu code is not + accessible. ## Blocks diff --git a/rpn.mu b/rpn.mu index 719fd03d..8214e420 100644 --- a/rpn.mu +++ b/rpn.mu @@ -15,7 +15,7 @@ # # Error handling is non-existent. This is just a prototype. -fn main screen: (addr screen), keyboard: (addr keyboard) { +fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { var in-storage: (stream byte 0x80) var in/esi: (addr stream byte) <- address in-storage var y/ecx: int <- copy 0