Compare commits

...

22 Commits

Author SHA1 Message Date
Juhani Krekelä e161d14321 Reset floppy disks upon read failure 2022-03-29 09:01:56 +03:00
Juhani Krekelä 48436ef9bd Put debug output behind debug define in io.asm 2022-03-29 09:01:56 +03:00
Juhani Krekelä 1c62da4e2d Update README with changes to the build system 2021-09-26 13:47:41 +03:00
Juhani Krekelä b9c83b11cd Implement date/time 2021-09-26 13:44:03 +03:00
Juhani Krekelä 68030372b7 Load and execute command.com 2021-09-26 11:46:50 +03:00
Juhani Krekelä 1967c06b85 Fix shift used for converting KiB to paragraphs
The old code was essentially a no-op due to x86 taking shifts mod 32.
This lead DOS to believe that it had 10KiB of memory, which is not
enough to contain io.sys, the DOS kernel, and command.com. This causes
command.com to overwrite the DOS kernel when it goes to relocate itself
at the end of the memory, leading to system crash.
2021-09-26 11:33:03 +03:00
Juhani Krekelä 2cab8ae6cf Update LICENSE and include it in disk images 2021-09-11 20:00:40 +03:00
Juhani Krekelä 9a7e047d57 Implement console IO 2021-09-10 19:39:58 +03:00
Juhani Krekelä 24e82f0fcd Rename dosbox.conf to dosbox-build.conf
Dosbox will override the default configuration with `dosbox.conf` if
launched with `dosbox .` in the source directory. Only override it for
building, not for interactive usage.
2021-09-10 19:36:11 +03:00
Wolfgang Müller d7778ecaef Introduce project-specific dosbox.conf
With the stock configuration, DOSBox limits the amount of instructions
it emulates each millisecond to a value it guesses. This is a reasonable
default to have when emulating games or other software from the time,
but woefully slow for our purposes of compilation.

Since the user's configuration file will most likely be tailored to
other uses, it makes sense, then, to use a project-specific
configuration here and override any user configuration. For now, set
only the cycles setting to 'max'.

The DOSBox invocation in the Makefile gets a bit long with the addition
of the -conf flag, so contain it in a variable instead.
2021-09-07 21:42:15 +03:00
Juhani Krekelä 5d9bc24eb2 Don't unnecessarily invoke dosbox when cleaning 2021-09-07 12:42:10 +03:00
Juhani Krekelä 7c6814f63c Add files used with Bochs debugging to .gitignore 2021-09-07 12:32:16 +03:00
Juhani Krekelä 7d99699b7e Open command.com in io.sys 2021-09-07 12:30:59 +03:00
Juhani Krekelä 007af45879 Use `db` instead of `dw` for number of FATs
Using `dw` ended up shifting all the values over by one byte, making DOS
think our 320K floppy was actually 16MiB in size, and had 46 sectors of
FAT instead of 1. This further lead it trash the setup stack and fail to
locate the disk directory.
2021-09-07 12:27:44 +03:00
Juhani Krekelä ee9acef473 Use mkfs.fat instead of mkdosfs for better portability 2021-08-26 13:12:38 +03:00
Juhani Krekelä 8ae365f4a7 Split build batch files to support parallel make 2021-08-26 13:07:31 +03:00
Juhani Krekelä ab809d01b1 Include development executables in the disk image 2021-08-26 12:38:40 +03:00
Juhani Krekelä b3ca33653f Start work on io.sys 2021-08-26 10:11:20 +03:00
Juhani Krekelä 094def1194 Add bootloader 2021-08-26 10:08:41 +03:00
Juhani Krekelä 86c9baa87b Use CR-LF endings everywhere 2021-08-26 06:24:26 +03:00
Juhani Krekelä 29e167c340 Add ordos.sys 2021-08-26 06:21:02 +03:00
Juhani Krekelä 92df43f146 Simplify licensing 2021-08-25 00:56:56 +03:00
15 changed files with 5038 additions and 170 deletions

4
.gitignore vendored
View File

@ -3,3 +3,7 @@
*.OBJ
*.COM
*.SYS
*.BIN
*.img
bochsrc.txt
tracing.notes

View File

@ -1,24 +1,23 @@
MS-DOS v1.25 and v2.0 Source Code
Copyright (c) Microsoft Corporation.
All rights reserved.
MIT License.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the Software),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Copyright (c) Microsoft Corporation.
Copyright (c) 2021 Juhani 'nortti' Krekelä and Ordos contributors
All rights reserved.
MIT License.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the Software),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,116 +0,0 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

30
Makefile Normal file
View File

@ -0,0 +1,30 @@
DOSBOX=dosbox -conf dosbox-build.conf -exit
ordos.img: BOOT.BIN IO.SYS ORDOS.SYS COMMAND.COM debug.com edlin.com exe2bin.exe link.exe masm.exe
rm -f ordos.img
mkfs.fat -C $@ -M 0xff 320
rw -I 0x7c00 -i BOOT.BIN -o $@ -c 512
mcopy -i $@ IO.SYS ::
mcopy -i $@ ORDOS.SYS ::
mcopy -i $@ COMMAND.COM ::
mcopy -i $@ debug.com ::
mcopy -i $@ edlin.com ::
mcopy -i $@ exe2bin.exe ::
mcopy -i $@ link.exe ::
mcopy -i $@ masm.exe ::
mcopy -i $@ LICENSE ::
BOOT.BIN: boot.asm
$(DOSBOX) mk-boot.bat
IO.SYS: io.asm
$(DOSBOX) mk-io.bat
ORDOS.SYS: msdos.asm stddos.asm
$(DOSBOX) mk-ordos.bat
COMMAND.COM: command.asm
$(DOSBOX) mk-comma.bat
clean:
rm -f ordos.img *.OBJ *.EXE *.COM *.BIN *.SYS

50
README
View File

@ -1,24 +1,26 @@
Ordos
=====
Ordos aims to be a buildable operating system based on MS-DOS 1.25.
File origins & License
----------------------
Here 'ms-dos' refers to the Microsoft repository, while 'tools' refers to
tools created for Ordos. Microsoft source code is under the MIT license,
while Ordos tools are CC0.
build.bat tools
clean.bat tools
command.asm ms-dos v1.25/source/COMMAND.ASM
debug.com ms-dos v1.25/bin/DEBUG.COM
edlin.com ms-dos v1.25/bin/EDLIN.COM
exe2bin.exe ms-dos v1.25/bin/EXE2BIN.EXE
link.exe ms-dos v1.25/bin/LINK.EXE
masm.exe ms-dos v2.0/bin/MASM.EXE
Notes
-----
MASM requires CR-LF line endings, while the Microsoft source code appers to
have LF.
Ordos
=====
Ordos aims to be a buildable operating system based on MS-DOS 1.25.
File origins & License
----------------------
Here 'ms-dos' refers to the Microsoft repository, while 'ordos' refers to
new files for Ordos. Build system files are all new for Ordos. Everything
is under the MIT license.
boot.asm ordos
command.asm ms-dos v1.25/source/COMMAND.ASM
debug.com ms-dos v1.25/bin/DEBUG.COM
edlin.com ms-dos v1.25/bin/EDLIN.COM
exe2bin.exe ms-dos v1.25/bin/EXE2BIN.EXE
io.asm ordos
link.exe ms-dos v1.25/bin/LINK.EXE
masm.exe ms-dos v2.0/bin/MASM.EXE
msdos.asm ms-dos v1.25/source/MSDOS.ASM
stddos.asm ms-dos v1.25/source/STDDOS.ASM
Notes
-----
MASM requires CR-LF line endings, while the Microsoft source code appers to
have LF.

170
boot.asm Normal file
View File

@ -0,0 +1,170 @@
; SPDX-License-Identifier: MIT
; Copyright (c) 2021 Juhani 'nortti' Krekelä.
iosegment segment at 60h
ioinit proc far
ioinit endp
iosegment ends
bootloader segment
assume cs:bootloader, ds:bootloader, es:bootloader, ss:bootloader
org 7c00h
jmp code
; BPB
db "Ordos " ; OEM Identifier
dw 512 ; Bytes per sector
db 2 ; Sectors per cluster
dw 1 ; Reserved sectors
db 2 ; FATs
dw 112 ; Root directory entries
dw 2*320 ; Total sectors
db 0ffh ; Media descriptor
dw 1 ; Sectors per fat
sectorspertrack dw 8
heads dw 2
dd 0 ; Hidden sectors
dd 0 ; Total sectors (large)
code:
cld
mov ax, cs
mov ds, ax
mov es, ax
cli
mov ss, ax
mov sp, 7c00h
sti
mov drivenumber, dl
; TODO: Check we actually have the OS
mov ax, 10
mov bx, 600h
mov cx, 17 ; This is what PC-DOS 1.10's full size ends up at
call loadsectors
mov si, offset success_msg
call printstr
jmp ioinit
; IN:
; ax = LBA of first sector
; es:bx = destination buffer
; cx = number of sectors to load
loadsectors proc
push ax
push cx
push dx
push di
loading_loop:
mov di, 3 + 1 ; Retry thrice, + 1 is since we dec first
retry:
push ax
push cx
chs:
xor dx, dx
; cylinder (track) - head - sector
; cylinder = LBA / sectorspertrack / heads
; head = LBA / sectorspertrack % heads
; sector = LBA % sectorspertrack + 1
div sectorspertrack
; ax = LBA / sectorspertrack
; dx = LBA % sectorspertrack
; sector
mov cl, dl
inc cl
xor dx, dx
div heads
; ax = LBA / sectorspertrack / heads
; dx = LBA / sectorspertrack % heads
; head
mov dh, dl
; cylinder (track)
mov ch, al
shr ax, 1
shr ax, 1
and al, 0c0h
or cl, al
mov ax, 0201h
mov dl, drivenumber
int 13h
jc disk_error
mov ax, 0e00h + '.'
int 10h
pop cx
pop ax
inc ax
add bx, 512
loop loading_loop
pop di
pop dx
pop cx
pop ax
ret
disk_error:
; Do we still have retries remaining?
dec di
jnz reset_disk
; No, die
mov si, offset error_msg
call printstr
hang:
hlt
jmp hang
reset_disk:
; Yes, reset disk and retry
xor ah, ah
int 13h
pop cx
pop ax
jmp retry
loadsectors endp
; IN:
; si = null-terminated string
printstr proc
lodsb
test al, al
jz ret_printstr
mov ah, 0eh
int 10h
jmp printstr
ret_printstr:
ret
printstr endp
drivenumber db (?)
success_msg db 13, 10, "DOS Loaded", 13, 10, 0
error_msg db 13, 10, "Disk error", 0
org 7c00h + 510
dw 0aa55h
bootloader ends
end

View File

@ -1,3 +1,15 @@
del command.obj
del command.exe
del command.com
del command.obj
del command.exe
del command.com
del stddos.obj
del stddos.exe
del ordos.sys
del boot.obj
del boot.exe
del boot.bin
del io.obj
del io.exe
del io.sys

2
dosbox-build.conf Normal file
View File

@ -0,0 +1,2 @@
[cpu]
cycles=max

704
io.asm Normal file
View File

@ -0,0 +1,704 @@
; SPDX-License-Identifier: MIT
; Copyright (c) 2021 Juhani 'nortti' Krekelä.
debug equ 1
iosegment equ 60h
dossegment equ iosegment + 1*1024/16 ; DOS starts 1KiB after IO system
dos segment at dossegment
org 0
dosinit proc far
dosinit endp
dos ends
code segment
code ends
constants segment
constants ends
data segment
data ends
iogroup group code, constants, data
code segment
assume cs:iogroup
org 0
; Jump table
jmp init ; 0000
jmp near ptr status ; 0003
jmp near ptr getch ; 0006
jmp near ptr putch ; 0009
jmp unimplemented ; 000c Output to printer
jmp unimplemented ; 000f Serial read
jmp unimplemented ; 0012 Serial write
jmp near ptr diskread ; 0015
jmp diskwrite ; 0018
jmp near ptr diskchange ; 001b
jmp near ptr setdate ; 001e
jmp near ptr settime ; 0021
jmp near ptr gettime ; 0024
jmp near ptr flush ; 0027
jmp near ptr mapdev ; 002a
init:
cld
cli
mov ax, cs
mov ds, ax
mov es, ax
; Put setup stack just below 32K
xor ax, ax
mov ss, ax
mov sp, 8000h
sti
; Figure out memory size
int 12h
; AX = memory size in kilobytes
; We want it in paragraphs
; There are 64 paragraphs in a kilobyte
mov cx, 6
shl ax, cl
; Memory size is passed in dx
mov dx, ax
if debug
call hexprint16
call newline
endif
; Disk table is passed in si
mov si, offset iogroup:disks_table
call dosinit
; Memory for command.com is at ds, with PSP already set up
; Retrieve amount of memory in the program segment
mov cx, word ptr ds:6
; Set up DTA
mov dx, 100h
mov ah, 1ah
int 21h
; Save command.com's segment for later and revert ds for opening the FCB
mov bx, ds
mov ax, cs
mov ds, ax
; Open command.com
mov dx, offset iogroup:command_fcb
mov ah, 0fh
int 21h
test al, al
jnz open_error
if debug
mov al, '+'
mov ah, 0eh
int 10h
endif
; Set random record field 0
mov word ptr iogroup:command_fcb+33, 0
mov word ptr iogroup:command_fcb+35, 0
; Set record size to 1 byte
mov word ptr iogroup:command_fcb+14, 1
; Read command.com into memory
mov ah, 27h
int 21h
jcxz read_error
cmp al, 1
jne read_error
if debug
mov ax, cx
call hexprint16
mov al, '.'
mov ah, 0eh
int 10h
endif
; Set up segments for command.com
mov ds, bx
mov es, bx
mov ss, bx
mov sp, 5ch ; Microsoft's documentation says to use this
; Put a zero at top of the stack
xor ax, ax
push ax
; Set default DTA
mov dx, 80h
mov ah, 1ah
int 21h
; Jump to command.com
push bx
mov ax, 100h
push ax
trampoline proc far
ret
trampoline endp
; TODO: Better error reporting
open_error:
mov al, '-'
jmp unfinished
read_error:
mov al, '!'
unfinished:
mov ah, 0eh
int 10h
jmp hang
; OUT:
; al = character if any
; zf = there were no characters
status proc far
push bx
push ax
mov ah, 1
int 16h
mov bl, al
pop ax
mov al, bl
pop bx
ret
status endp
; OUT:
; al = character
getch proc far
push bx
push ax
xor ah, ah
int 16h
mov bl, al
pop ax
mov al, bl
pop bx
ret
getch endp
; IN:
; al = character
putch proc far
push ax
mov ah, 0eh
int 10h
pop ax
ret
putch endp
; IN:
; al = driver number
; ds:bx = buffer
; cx = number of sectors to read
; dx = LBA of first sector
; OUT:
; TODO: Document
diskread proc far
if debug
push ax
mov ax, 0e00h + 'r'
int 10h
pop ax
call far_caller
push ax
call hexprint8
call space
mov ax, ds
call hexprint16
call space
mov ax, bx
call hexprint16
call space
mov ax, cx
call hexprint16
call space
mov ax, dx
call hexprint16
call newline
pop ax
endif
; TODO: Everything except sregs can be trashed
push es
push ax
push bx
push cx
push dx
push di
; Save driver number
push ax
; BIOS uses es:bx instead of ds:bx
mov ax, ds
mov es, ax
mov ax, dx
; Put drive(r) number in dl
pop dx
sector_read_loop:
jcxz ret_diskread
mov di, 3 + 1 ; 3 retries, + 1 since we dec first
try_sector_read:
push ax
push cx
call chs
mov ah, 2
mov al, 1
int 13h
jnc sector_read_success
dec di
jz sector_read_fail
reset_disk:
if debug
mov al, '"'
mov ah, 0eh
int 10h
endif
xor ax, ax
int 13h
pop cx
pop ax
jmp try_sector_read
sector_read_fail:
mov al, ah
if debug
call hexprint8;debg
endif
mov al, '?'
mov ah, 0eh
int 10h
pop cx
pop ax
pop di
pop dx
pop ax ; Would be cx, don't overwrite
pop bx
pop ax
pop es
mov al, 12 ; TODO: Don't hardcode
stc
ret
sector_read_success:
pop cx
pop ax
dec cx
inc ax
add bx, 512
jmp sector_read_loop
ret_diskread:
pop di
pop dx
pop cx
pop bx
pop ax
pop es
clc
ret
diskread endp
; IN:
; ax = LBA
; OUT:
; ch = cylinder
; cl = sector & 2 high bits of cylinder
; dh = head
chs proc
push ax
push dx
xor dx, dx
; cylinder (track) - head - sector
; cylinder = LBA / sectorspertrack / heads
; head = LBA / sectorspertrack % heads
; sector = LBA % sectorspertrack + 1
div iogroup:sectorspertrack
; ax = LBA / sectorspertrack
; dx = LBA % sectorspertrack
; sector
mov cl, dl
inc cl
xor dx, dx
div iogroup:heads
; ax = LBA / sectorspertrack / heads
; dx = LBA / sectorspertrack % heads
; head
mov dh, dl
; cylinder (track)
mov ch, al
shr ax, 1
shr ax, 1
and al, 0c0h
or cl, al
mov ax, dx
pop dx
mov dh, ah
pop ax
ret
chs endp
diskwrite:
mov al, 'w'
jmp error
; IN:
; al = drive
; OUT:
; ah = -1 different / 0 dunno / 1 same
; cf = 0 -> al = driver num
; cf = 1 -> al = disk error code
diskchange proc far
; TODO: Implement
mov ax, 0000h
clc
ret
diskchange endp
; IN:
; ax = days since 1980-01-01
setdate proc far
mov iogroup:days_since_epoch, ax
ret
setdate endp
; IN:
; ch = hour
; cl = minute
; dh = second
; dl = 1/100 second
settime proc far
push ax
push bx
push cx
push dx
push si
push di
; Save second & 1/100 second in bx
mov bx, dx
; Hour
mov al, ch
cbw
mul iogroup:doubleticks_per_hour
shl ax, 1
rcl dx, 1
; Store the partial sum in si:di
mov di, ax
mov si, dx
; Minute
mov al, cl
cbw
mul iogroup:ticks_per_minute
add di, ax
adc si, dx
; Second
mov al, bh
cbw
mul iogroup:ticks_per_second
add di, ax
adc si, dx
; 1/100 second
mov al, bl
cbw
div iogroup:cs_per_tick
xor ah, ah
add di, ax
adc si, 0
; Move result to cx:ds and set timer
mov cx, si
mov dx, di
mov ah, 01h
int 1ah
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
settime endp
; OUT:
; ax = days since 1980-01-01
; ch = hour
; cl = minute
; dh = second
; dl = 1/100 second
gettime proc far
; TODO: Use RTC if available
push bx
; Get ticks since midnight and day rollover flag
xor ah, ah
int 1ah
; al is nonzero if day has changed
test al, al
jz same_day
inc iogroup:days_since_epoch
same_day:
; Divide the ticks by 2, to keep all our arithmetic within bounds
shr cx, 1
rcr dx, 1
; int 1ah / ah=00 returns the ticks in cx:dx, div operates on dx:ax
mov ax, dx
mov dx, cx
div iogroup:doubleticks_per_hour
mov ch, al ; Hour
; Remainder in dx, range [0,doubleticks_per_hour[ represents an hour
; Multiply by 60, divide by doubleticks_per_hour to get the minute
mov ax, dx
mul iogroup:sixty
div iogroup:doubleticks_per_hour
mov cl, al ; Minute
; Do same again to get seconds
mov ax, dx
mul iogroup:sixty
div iogroup:doubleticks_per_hour
mov bl, al ; Save seconds in bl, since dh gets destroyed by next muldiv
; For 1/100th of a second, multiply by 100 instead
mov ax, dx
mul iogroup:hundred
div iogroup:doubleticks_per_hour
mov dh, bl ; Second
mov dl, al ; 1/100 second
mov ax, iogroup:days_since_epoch
pop bx
ret
gettime endp
flush proc far
push ax
flush_loop:
mov ah, 1
int 16h
jz flush_ret
xor ah, ah
int 16h
jmp flush_loop
flush_ret:
pop ax
ret
flush endp
mapdev proc far
; TODO: Implement
ret
mapdev endp
unimplemented:
mov al, '@'
error:
mov ah, 0eh
int 10h
mov ah, 0eh
mov al, '!'
int 10h
if debug
call far_caller
endif
hang:
hlt
jmp hang
code ends
; TODO: STRUC?
constants segment
sectorspertrack dw 8 ; TODO: Don't hardcode
heads dw 2 ; TODO: Don't hardcode
disks_table:
db 1 ; 1 drive, TODO: Don't hardcode
db 0 ; Physical drive 0
dw offset iogroup:parameters_320k
parameters_320k:
dw 512 ; Sector size in bytes
db 2 ; Sectors per cluster
dw 1 ; Number of reserved sectors
db 2 ; Number of FATs
dw 112 ; Number of directory entries
dw 320*2 ; Number of sectors
doubleticks_per_hour dw 32772 ; 1800B0h / 2 / 24
ticks_per_minute dw 1092 ; 1800B0h / 24 / 60
ticks_per_second dw 18 ; 1800B0h / 24 / 60 / 60
cs_per_tick db 5 ; 24 * 60 * 60 * 100 / 1800B0h
sixty dw 60
hundred dw 100
constants ends
data segment
command_fcb:
db 1 ; First drive, TODO: Don't hardcode
db "COMMAND COM"
db 25 dup (?)
days_since_epoch: dw 0
data ends
code segment
if debug
hexprint16 proc
xchg al, ah
call hexprint8
xchg al, ah
hexprint8 proc
rol al, 1
rol al, 1
rol al, 1
rol al, 1
call hexprint4
rol al, 1
rol al, 1
rol al, 1
rol al, 1
hexprint4 proc
push ax
and al, 0fh
cmp al, 9
jbe under_10
add al, 'a' - 10 - '0'
under_10:
add al, '0'
mov ah, 0eh
int 10h
pop ax
ret
hexprint4 endp
hexprint8 endp
hexprint16 endp
newline proc
push ax
mov ax, 0e0dh
int 10h
mov ax, 0e0ah
int 10h
pop ax
ret
newline endp
space proc
push ax
mov ax, 0e20h
int 10h
pop ax
ret
space endp
far_caller proc
push ax
push bx
mov bx, sp
mov ax, [ss:bx + 8]
call hexprint16
mov al, ':'
mov ah, 0eh
int 10h
pop bx
pop ax
near_caller proc
push ax
push bx
mov bx, sp
mov ax, [ss:bx + 6]
call hexprint16
call space
pop bx
pop ax
ret
near_caller endp
far_caller endp
logaddr proc
push ax
push bx
mov al, '>'
mov ah, 0eh
int 10h
mov bx, sp
mov ax, [ss:bx + 4]
call hexprint16
call space
pop bx
pop ax
ret
logaddr endp
endif
code ends
end

3
mk-boot.bat Normal file
View File

@ -0,0 +1,3 @@
masm boot;
link boot;
exe2bin boot.exe boot.bin

View File

@ -1,3 +1,3 @@
masm command;
link command;
exe2bin command.exe command.com
masm command;
link command;
exe2bin command.exe command.com

3
mk-io.bat Normal file
View File

@ -0,0 +1,3 @@
masm io;
link io;
exe2bin io.exe io.sys

3
mk-ordos.bat Normal file
View File

@ -0,0 +1,3 @@
masm stddos;
link stddos;
exe2bin stddos.exe ordos.sys

4030
msdos.asm Normal file

File diff suppressed because it is too large Load Diff

22
stddos.asm Normal file
View File

@ -0,0 +1,22 @@
TITLE MS-DOS version 1.25 by Tim Paterson March 3, 1982
PAGE 60,132
; Use the following booleans to set the switches
FALSE EQU 0
TRUE EQU NOT FALSE
; Use the switches below to produce the standard Microsoft version of the IBM
; version of the operating system
MSVER EQU FALSE
IBM EQU TRUE
; Set this switch to cause DOS to move itself to the end of memory
HIGHMEM EQU FALSE
; Turn on switch below to allow testing disk code with DEBUG. It sets
; up a different stack for disk I/O (functions > 11) than that used for
; character I/O which effectively makes the DOS re-entrant.
DSKTEST EQU FALSE
INCLUDE MSDOS.ASM