From b34b0ea74e983390304bdd1ac51e5b9525e1b65a Mon Sep 17 00:00:00 2001 From: CrazyEttin <> Date: Fri, 27 Aug 2021 20:25:46 +0300 Subject: [PATCH] Add new under construction system calls to the readme and change the one for loading files to accomodate them, move the disk parameters to the main namespace in anticipation of restructuring the disk operations with the addition of the new system calls, rewrite parts of system to remove essentially duplicate code, and rewrite the explanation of the file system in the readme. --- README.MD | 47 ++++++++++++++++--------- src/BOOT.ASM | 3 +- src/LOADF.INC | 90 +++++++++++++++++++++-------------------------- src/PRINT.ASM | 2 +- src/SYSTEM.ASM | 95 +++++++++++++++++++++++++++++--------------------- 5 files changed, 129 insertions(+), 108 deletions(-) diff --git a/README.MD b/README.MD index 8f852cd..74bb71e 100644 --- a/README.MD +++ b/README.MD @@ -1,9 +1,9 @@ EttinOS ======= -EttinOS is a minimalist 16-bit DOS-like hobbyist operating system for -the IBM Personal Computer and compatible machines. Its git repository -can be found at https://ahti.space/git/crazyettin/EttinOS and that of +EttinOS is a minimalist 16-bit hobbyist disk operating system for the +IBM Personal Computer and compatible machines. Its git repository can be +found at https://ahti.space/git/crazyettin/EttinOS and that of EttinOS-extra, a collection of programs for the system, at https://ahti.space/git/crazyettin/EttinOS-extra. @@ -39,13 +39,11 @@ The input system is inspired by typewriters. Typing a character overwrites the cursor location and the erase (=tab) key erases it. The space and backspace keys move the cursor. -EttinOS assigns the drives letters from A to D and uses the FAT12 file -system. The hidden and total sectors entries of the BIOS parameter -block, the entire extended BIOS parameter block, file attributes, and -the file access date are not supported and are ignored if present: as a -result disk labels and subdirectories are not supported. Drive letters -and file names are case-insensitive and the latter follow the 8.3 -format. Text files use CRLF line endings. +EttinOS assigns the drives letters from A to D and uses a version of the +MS-DOS 3.0 FAT12 file system (in actual use since 2.1) without support +for file attributes and thus disk labels and subdirectories. Drive +letters and file names are case-insensitive and the latter follow the +8.3 format. Text files use CRLF line endings. Drives and files are specified as ([A-D]:) and ([A-D]:)FILENAME.EXT respectively. Specifying the current drive, indicated in the prompt, is @@ -53,11 +51,11 @@ optional. A command can be followed by arguments separated from eachother and the command with spaces. Extra spaces are ignored. Commands other than -changing the drive are stored as external programs: the command for a -program is its file specification without the extension. +changing the current drive are stored as external programs: the command +for a program is its file specification without the extension. Commands included in EttinOS: - * [A-D]:: Change the drive. + * [A-D]:: Change the current drive. * ECHO: Print a message. Syntax: ECHO Message to be printed * HELLO: Print "Hello world!". * LIST: Print a list of the files on a drive. Syntax: LIST DRIVE @@ -80,7 +78,7 @@ has finished running. System calls: * Interrupt 0x20: Return to the shell. - * Interrupt 0x21: Input and output: + * Interrupt 0x21: String operations: * AH = 0x0: Print a string ending in a null from SI. * AH = 0x1: Read a string ending in a null of at most AL characters to DI until a return. @@ -88,8 +86,25 @@ System calls: CRLF. * AH = 0x3: Read a string ending in a null of at most AL characters to DI until a return and print a CRLF. + * AH = 0x4: (Under construction) Convert a decimal string ending + in a null at SI to a value in AL. + * AH = 0x5: (Under construction) Convert a value in AL to a + decimal string ending in a null at DI. + * AH = 0x6: (Under construction) Convert a hexadecimal string + ending in a null at SI to a value in AL. + * AH = 0x7: (Under construction) Convert a value in AL to a + hexadecimal string ending in a null at DI. * Interrupt 0x22: Disk operations: - * AH = 0x0: Load a file named at SI as a string ending in a null + * AH = 0x0: (Under construction) Load the directory of a drive + named at SI as a string ending in a null to the offset + BX and store the error codes in AL: + * AL = 0x0: Succesful load + * AL = 0x1: Drive not found + * AL = 0x2: Unable to read disk + * AH = 0x1: (Under construction) Store a directory at the offset + BX to a drive named at SI as a string ending in a + null. + * AH = 0x2: Load a file named at SI as a string ending in a null to the offset BX and store the file size in CX and the error codes in AL: * AL = 0x0: Succesful load @@ -97,7 +112,7 @@ System calls: * AL = 0x2: Unable to read disk * AL = 0x4: File or command not found * AL = 0x8: Not enough memory - * AH = 0x1: Save a file (under construction). + * AH = 0x3: (Under construction) Save a file. Known bugs ---------- diff --git a/src/BOOT.ASM b/src/BOOT.ASM index 3b112e3..e6f8532 100644 --- a/src/BOOT.ASM +++ b/src/BOOT.ASM @@ -23,6 +23,7 @@ mediadescriptor db 0xf0 sectorsperfat dw 0x9 sectorspertrack dw 0x12 heads dw 0x2 +hiddensectors dw 0x0 %else @@ -37,10 +38,10 @@ mediadescriptor db 0xfd sectorsperfat dw 0x2 sectorspertrack dw 0x9 heads dw 0x2 +hiddensectors dw 0x0 %endif - ;Setup ;Set the segments start: diff --git a/src/LOADF.INC b/src/LOADF.INC index 83aabe0..b7af675 100644 --- a/src/LOADF.INC +++ b/src/LOADF.INC @@ -16,8 +16,8 @@ push di ;Store the current drive and offset mov word [.pointer], bx -mov dl, byte [drive] -mov byte [.drive], dl +mov dl, byte [curdrive] +mov byte [drive], dl ;Change the drive if needed ;Check for a drive specification @@ -53,7 +53,7 @@ mov cx, 0x0 jmp .done ;Change the drive .contchdrive: -mov [.drive], dl +mov [drive], dl ;Move to the file name add si, 0x2 @@ -112,7 +112,7 @@ pop ax ;Load the disk description table ;Set the source -mov dl, [.drive] +mov dl, [drive] mov ch, 0x0 mov dh, 0x0 mov cl, 0x1 @@ -136,48 +136,48 @@ jmp .done ;Store the disk values used for the rest of the call .storevalues: mov ax, [buffer + 0xb] -mov [.sectorsize], ax +mov [sectorsize], ax mov al, [buffer + 0xd] -mov [.clustersize], al +mov [clustersize], al mov ax, [buffer + 0xe] -mov [.reservedsectors], ax +mov [reservedsectors], ax mov al, [buffer + 0x10] -mov [.fats], al +mov [fats], al mov ax, [buffer + 0x11] -mov [.rootentries], ax +mov [rootentries], ax mov ax, [buffer + 0x16] -mov [.sectorsperfat], ax +mov [sectorsperfat], ax mov ax, [buffer + 0x18] -mov [.sectorspertrack], ax +mov [sectorspertrack], ax mov ax, [buffer + 0x1a] -mov [.heads], ax +mov [heads], ax ;Calculate and store variables not found in the BPB ;Start of the root mov ah, 0x0 -mov al, [.fats] -mul word [.sectorsperfat] -add ax, [.reservedsectors] -mov [.rootstart], ax +mov al, [fats] +mul word [sectorsperfat] +add ax, [reservedsectors] +mov [rootstart], ax ;Size of the root in sectors -mov ax, [.rootentries] +mov ax, [rootentries] mov dx, 0x20 mul dx mov dx, 0x0 -div word [.sectorsize] -mov [.rootsectors], ax +div word [sectorsize] +mov [rootsectors], ax ;Start of data -add ax, [.rootstart] -mov [.datastart], ax +add ax, [rootstart] +mov [datastart], ax ;Load the root ;Set the source -mov ax, [.rootstart] +mov ax, [rootstart] ;Set the destination mov si, buffer mov bx, si ;Set the size -mov cx, [.rootsectors] +mov cx, [rootsectors] ;Store the source and the loop counter in the stack .loadrootsector: push ax @@ -194,7 +194,7 @@ pop cx pop ax ;Set the next sector add ax, 0x1 -add bx, word [.sectorsize] +add bx, word [sectorsize] ;Load the next sector loop .loadrootsector @@ -202,7 +202,7 @@ loop .loadrootsector ;Set DI to the root mov di, buffer ;Set the number of root entries -mov cx, word [.rootentries] +mov cx, word [rootentries] ;Set the entry pointer mov ax, 0x0 ;Store the loop counter in the stack @@ -238,8 +238,8 @@ cmp word [di + 0x13], 0x0 jne .sizerror ;Get the cluster size in bytes mov ah, 0x0 -mov al, [.clustersize] -mul word [.sectorsize] +mov al, [clustersize] +mul word [sectorsize] mov bx, ax ;Store the file size mov ax, [di + 0x11] @@ -267,12 +267,12 @@ jmp .done mov ax, [di + 0xf] mov [.cluster], ax ;Set the source -mov ax, [.reservedsectors] +mov ax, [reservedsectors] call .calcsource ;Set the destination mov bx, buffer ;Set the size -mov ax, [.sectorsperfat] +mov ax, [sectorsperfat] ;Load the FAT mov ah, 0x2 int 0x13 @@ -282,13 +282,13 @@ int 0x13 ;Set the source mov ax, word [.cluster] sub ax, 0x2 -mul byte [.clustersize] -add ax, [.datastart] +mul byte [clustersize] +add ax, [datastart] ;Set the destination mov bx, word [.pointer] ;Set the size mov ch, 0x0 -mov cl, byte [.clustersize] +mov cl, byte [clustersize] ;Store the loop counter in the stack .loadsector: push cx @@ -303,7 +303,7 @@ int 0x13 pop ax ;Set the next sector add ax, 0x1 -add bx, word [.sectorsize] +add bx, word [sectorsize] ;Load the loop counter from the stack pop cx ;Load the next sector @@ -335,8 +335,8 @@ jge .success ;Store the address of the next cluster mov word [.cluster], ax ;Set the destination of the next cluster -mov ax, [.sectorsize] -mul word [.clustersize] +mov ax, [sectorsize] +mul word [clustersize] add word [.pointer], ax ;Load the next cluster jmp .loadcluster @@ -362,18 +362,6 @@ mov ah, 0x0 iret ;Data -.drive db 0x0 -.sectorsize dw 0x0 ;bytes -.clustersize db 0x0 ;sectors -.reservedsectors dw 0x0 -.fats db 0x0 -.rootentries dw 0x0 -.sectorsperfat dw 0x0 -.sectorspertrack dw 0x0 -.heads dw 0x0 -.rootstart dw 0x0 -.rootsectors dw 0x0 -.datastart dw 0x0 .file times 0xb db 0x20 .size dw 0x0 .cluster dw 0x0 @@ -454,21 +442,21 @@ push bx mov bx, ax ;Calculate the sector mov dx, 0x0 -div word [.sectorspertrack] +div word [sectorspertrack] add dl, 0x1 mov cl, dl ;Load the logical sector from BX mov ax, bx ;Calculate the head and cylinder mov dx, 0x0 -div word [.sectorspertrack] +div word [sectorspertrack] mov dx, 0x0 -div word [.heads] +div word [heads] mov dh, dl ;Head mov ch, al ;Cylinder ;Load the drive number -mov dl, byte [.drive] +mov dl, byte [drive] ;Load BX and AX from the stack pop bx diff --git a/src/PRINT.ASM b/src/PRINT.ASM index 7e571b2..11586da 100644 --- a/src/PRINT.ASM +++ b/src/PRINT.ASM @@ -40,7 +40,7 @@ stosb ;Load load: mov bx, stack + 0x100 -mov ah, 0x0 +mov ah, 0x2 int 0x22 ;Check for errors cmp al, 0x0 diff --git a/src/SYSTEM.ASM b/src/SYSTEM.ASM index 22079c1..b5e52b0 100644 --- a/src/SYSTEM.ASM +++ b/src/SYSTEM.ASM @@ -21,7 +21,7 @@ je readln iret ;Disk operations int0x22: -cmp ah, 0x0 +cmp ah, 0x2 je loadf ;To do: savef iret @@ -50,9 +50,10 @@ mov [0x82], ax mov [0x86], ax mov [0x8a], ax -;Store the boot drive number and set the drive letter -mov [drive], dl -call setdriveletter +;Store the boot drive number as the current drive and set the current +;drive letter +mov [curdrive], dl +call setcurdriveletter ;Print a welcome message mov si, welcomemsg @@ -67,8 +68,8 @@ mov sp, 0x0 sti ;Prompt for and read a command -;Print the drive letter -mov si, driveletter +;Print the current drive letter +mov si, curdriveletter mov ah, 0x0 int 0x21 ;Print a prompt @@ -85,26 +86,24 @@ int 0x21 cmp byte [input], 0x0 jz shell -;Check for a drive change command +;Set SI at the command ;Set SI at input mov si, input ;Ignore leading spaces call ignoreleading -;Check + +;Check for a current drive change command cmp byte [si + 0x1], ":" jne extract cmp byte [si + 0x2], 0x0 -je changedrive +je changecurdrive cmp byte [si + 0x2], 0x20 -je changedrive +je changecurdrive ;Extract the specification of the program file extract: -;Set SI at input and DI at program -mov si, input +;Set DI at program mov di, program -;Ignore leading spaces -call ignoreleading ;Initialise program with spaces mov cx, 0xe mov al, 0x20 @@ -142,21 +141,28 @@ rep movsb ;Load the program mov bx, 0x3000 mov si, program -mov ah, 0x0 +mov ah, 0x2 int 0x22 ;Check for errors cmp al, 0x0 jne shell -;Pass the drive and command tail to the program -mov dl, [drive] +;Pass the current drive and command tail to the program +mov dl, [curdrive] pop si call ignoreleading ;Execute the program jmp 0x3000 -;Change the drive +;Print a command error message and return to the shell +cmderror: +mov si, cmderrormsg +mov ah, 0x2 +int 0x21 +jmp shell + +;Change the current drive ;Get the BIOS equipment list -changedrive: +changecurdrive: int 0x11 ;Get the number of floppy drives times 0x6 shr ax, 0x1 @@ -184,33 +190,44 @@ int 0x21 jmp shell ;Change the drive contchdrive: -mov [drive], dl -call setdriveletter +mov [curdrive], dl +call setcurdriveletter jmp shell -;Print a command error message and return to the shell -cmderror: -mov si, cmderrormsg -mov ah, 0x2 -int 0x21 -jmp shell +;Welcome message +welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0 -;Data -welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0 -drive db 0x0 -driveletter db "?:", 0x0 +;Drive stuff +curdrive db 0x0 driveletters db "AaBbCcDd" -prompt db "> ", 0x0 -input times 0x4c db 0x0 -program times 0xf db 0x0 -extension db ".BIN", 0x0 -cmderrormsg db "File or command not found", 0x0 -driverrormsg db "Drive not found", 0x0 + +;Shell +curdriveletter db "?:", 0x0 +prompt db "> ", 0x0 +input times 0x4c db 0x0 +program times 0xf db 0x0 +extension db ".BIN", 0x0 +cmderrormsg db "File or command not found", 0x0 +driverrormsg db "Drive not found", 0x0 + +;Disk parameters +drive db 0x0 +sectorsize dw 0x0 ;bytes +clustersize db 0x0 ;sectors +reservedsectors dw 0x0 +fats db 0x0 +rootentries dw 0x0 +sectorsperfat dw 0x0 +sectorspertrack dw 0x0 +heads dw 0x0 +rootstart dw 0x0 +rootsectors dw 0x0 +datastart dw 0x0 ;*** ;Set the drive letter -setdriveletter: +setcurdriveletter: ;Set the drive number and letter counters mov dh, 0x0 @@ -227,7 +244,7 @@ jmp .checkdrive ;Set the drive letter .set: mov al, [si] -mov byte [driveletter], al +mov byte [curdriveletter], al ;Return ret