explicitly pass data disk to main
This commit is contained in:
parent
9818f1de98
commit
7bf8adb893
4
400.mu
4
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
|
||||
|
|
395
boot.subx
395
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
|
||||
|
|
2
ex10.mu
2
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
|
||||
|
|
2
ex2.mu
2
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
|
||||
|
|
2
ex3.mu
2
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
|
||||
{
|
||||
|
|
2
ex4.mu
2
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
|
||||
}
|
||||
|
|
2
ex5.mu
2
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
|
||||
}
|
||||
|
|
2
ex6.mu
2
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
|
||||
|
|
2
ex7.mu
2
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
|
||||
{
|
||||
|
|
2
ex8.mu
2
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
|
||||
}
|
||||
|
|
6
ex9.mu
6
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 {
|
||||
|
|
2
life.mu
2
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
|
||||
|
|
|
@ -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
5
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
|
||||
|
||||
|
|
2
rpn.mu
2
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
|
||||
|
|
Loading…
Reference in New Issue