explicitly pass data disk to main

This commit is contained in:
Kartik K. Agaram 2021-03-27 17:47:23 -07:00
parent 9818f1de98
commit 7bf8adb893
15 changed files with 316 additions and 118 deletions

4
400.mu
View File

@ -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

395
boot.subx
View File

@ -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

View File

@ -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

2
ex2.mu
View File

@ -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

2
ex3.mu
View File

@ -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
{

2
ex4.mu
View File

@ -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
}

2
ex5.mu
View File

@ -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
}

2
ex6.mu
View File

@ -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

2
ex7.mu
View File

@ -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
{

2
ex8.mu
View File

@ -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
}

6
ex9.mu
View File

@ -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 {

View File

@ -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

View File

@ -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

5
mu.md
View File

@ -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

2
rpn.mu
View File

@ -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