First commit
This commit is contained in:
commit
62e1d36c38
23 files changed
+2501
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.sublime*
|
||||||
|
*.img
|
||||||
|
*.bin
|
||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
BITS 16
|
||||||
|
;CLI
|
||||||
|
|
||||||
|
;Command syntax: <command name> <arg1>
|
||||||
|
;Argument must not contain spaces.
|
||||||
|
|
||||||
|
; Data
|
||||||
|
CLI_Command_Buffer times 256 db 0
|
||||||
|
CLI_Command_Length dw 0
|
||||||
|
|
||||||
|
; API
|
||||||
|
; args:
|
||||||
|
; ax: keyboard keycode.
|
||||||
|
CLI_ASCII_INPUT:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; Fetch command buffer offset.
|
||||||
|
; If there is no room in the buffer, then just bail on the key press.
|
||||||
|
mov bx, [CLI_Command_Length]
|
||||||
|
cmp bx, 255
|
||||||
|
je .end
|
||||||
|
|
||||||
|
inc bx ; The new last element will be located at this offset.
|
||||||
|
mov [CLI_Command_Length], bx ; Save the new counter.
|
||||||
|
dec bx ; Go back to the index the character should be written to.
|
||||||
|
|
||||||
|
; Move new ascii character into command buffer.
|
||||||
|
add bx, CLI_Command_Buffer ; address+offset = destination
|
||||||
|
mov [bx], al
|
||||||
|
|
||||||
|
inc bx
|
||||||
|
mov byte [bx], 0
|
||||||
|
|
||||||
|
; Print out the input character
|
||||||
|
mov ah, 0xe ; Teletype output
|
||||||
|
mov bl, 0x02 ; color (green)
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
.end:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; args:
|
||||||
|
CLI_DELETE:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; Check if at the beginning of the line.
|
||||||
|
mov bx, [CLI_Command_Length]
|
||||||
|
cmp bx, 0x00
|
||||||
|
je .end
|
||||||
|
|
||||||
|
; Move the counter one back
|
||||||
|
sub bx, 0x01
|
||||||
|
mov [CLI_Command_Length], bx
|
||||||
|
|
||||||
|
;Move NULL into the last character of the line (delete)
|
||||||
|
mov al, 0x0
|
||||||
|
add bx, CLI_Command_Buffer ; address+offset = destination
|
||||||
|
mov [bx], al
|
||||||
|
|
||||||
|
; Go back one space
|
||||||
|
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Place a NULL
|
||||||
|
mov al, 0x0 ; NULL
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Go back one space again as the above print of NULL pushes the cursor forward again.
|
||||||
|
mov ax, 0x0e08
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
.end:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Probably activated with the 'Enter' button.
|
||||||
|
CLI_CONFIRM_INPUT:
|
||||||
|
|
||||||
|
call CLI_EXECUTE
|
||||||
|
|
||||||
|
mov bx, 0
|
||||||
|
mov [CLI_Command_Length], bx
|
||||||
|
mov [CLI_Command_Buffer], bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
print_help_message:
|
||||||
|
; Prints a list of available commands
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push si
|
||||||
|
mov si, .command_list_string
|
||||||
|
call print
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
.command_list_string:
|
||||||
|
db 13, 10
|
||||||
|
db "Available commands:", 13, 10
|
||||||
|
db " help: Prints this screen", 13, 10
|
||||||
|
db " dumpmem: Prints the contents of a memory region (At the moment hardcoded)", 13, 10
|
||||||
|
db " keyprint: Prints the character and keycode for a key presssd", 13, 10
|
||||||
|
db " clear: Clears the screen", 13, 10
|
||||||
|
db " formatdisk: Initialize the file system", 13, 10
|
||||||
|
db " createfile: Name a file, in the file system", 13, 10
|
||||||
|
db " fsinfo: Displays info about the file system", 13, 10
|
||||||
|
db " ls: Lists the named files", 13, 10
|
||||||
|
db " svim: SingOS' text editor", 13, 10, 0
|
||||||
|
|
||||||
|
; Executes the command.
|
||||||
|
CLI_EXECUTE:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov bx, [CLI_Command_Length]
|
||||||
|
cmp bx, 0
|
||||||
|
je near .end ; If there are not bytes in the buffer then there is no command.
|
||||||
|
|
||||||
|
mov ax, [.Num_Commands] ; The number of commands available.
|
||||||
|
|
||||||
|
lea si, [CLI_Command_Buffer]
|
||||||
|
mov cx, 0 ; Index into the list of commands.
|
||||||
|
|
||||||
|
.Interpreter_Search_Commands_Loop:
|
||||||
|
;cmp cx, ax ; Start by comparing.
|
||||||
|
;je .end
|
||||||
|
|
||||||
|
mov bx, cx ; Move Index into bx to offset into the array of commands.
|
||||||
|
add bx, bx ; The pointers are two bytes long. This compensates for that.
|
||||||
|
|
||||||
|
mov bx, [.Command_Name_List + bx] ; Fetch the pointer for the string.
|
||||||
|
|
||||||
|
lea di, [bx]
|
||||||
|
call stringcompare
|
||||||
|
|
||||||
|
je .Interpreter_Command_Execute
|
||||||
|
|
||||||
|
inc cx ; Prepare for next iteration.
|
||||||
|
cmp ax, cx
|
||||||
|
je .end
|
||||||
|
jmp .Interpreter_Search_Commands_Loop
|
||||||
|
|
||||||
|
|
||||||
|
.Interpreter_Command_Execute:
|
||||||
|
mov bx, cx ; Move Index into bx to offset into the array of commands.
|
||||||
|
add bx, bx ; The pointers are two bytes long. This compensates for that.
|
||||||
|
|
||||||
|
pusha
|
||||||
|
call printCRLF
|
||||||
|
popa
|
||||||
|
|
||||||
|
mov dx, [.Command_Function_Pointers + bx] ; Program pointer
|
||||||
|
|
||||||
|
; Execute program.
|
||||||
|
call dx
|
||||||
|
|
||||||
|
.end:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.tmp dw 0
|
||||||
|
.Num_Commands dw 9
|
||||||
|
.Command_Name_List dw .CMD1, .CMD2, .CMD3, .CMD4, .CMD5, .CMD6, .CMD7, .CMD8, .CMD9
|
||||||
|
.Command_Function_Pointers dw dumpmem_hardcoded_args, keyprint, svim, vsfs_list_files_command, vsfs_create_file, vsfs_format_disk, vsfs_get_fs_info, os_clear_screen, print_help_message
|
||||||
|
.CMD1 db 'dumpmem', 0
|
||||||
|
.CMD2 db 'keyprint', 0
|
||||||
|
.CMD3 db 'svim', 0
|
||||||
|
.CMD4 db 'ls', 0
|
||||||
|
.CMD5 db 'createfile', 0
|
||||||
|
.CMD6 db 'formatdisk', 0
|
||||||
|
.CMD7 db 'fsinfo', 0
|
||||||
|
.CMD8 db 'clear', 0
|
||||||
|
.CMD9 db 'help', 0
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
SingOS is a single task operating system.
|
||||||
|
|
||||||
|
Current version 0.0.3
|
||||||
|
|
||||||
|
The goal for this project is to create a Operating System
|
||||||
|
which tries to find new better ways to handle memory adressing
|
||||||
|
|
||||||
|
It will also be posible to switch between 16, 32 and 64-bit mode
|
||||||
|
such that anything on very low level can be tested.
|
||||||
|
|
||||||
|
You can build and run the OS with following command
|
||||||
|
(Require nasm and qemu installed)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
|
||||||
|
sh build.sh
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If you only want to run SingOS:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
|
||||||
|
sh build.sh run
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If you only want to compile the binary:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
|
||||||
|
sh build.sh make
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to write it to a usb device
|
||||||
|
```sh
|
||||||
|
sudo dd if=/some_dir/SingOS.img of=/dev/name_device status=progress oflag=sync
|
||||||
|
```
|
||||||
+235
@@ -0,0 +1,235 @@
|
|||||||
|
BITS 16
|
||||||
|
;http://www.ousob.com/ng/bios/ng1223.php
|
||||||
|
start:
|
||||||
|
; Set up 4K stack after this bootloader
|
||||||
|
; [Remember: Effective Address = Segment*16 + Offset]
|
||||||
|
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16
|
||||||
|
add ax, 0x20 ; Skip over the size of the bootloader divided by 16
|
||||||
|
mov ss, ax ; Set 'ss' to this location (the beginning of our stack region)
|
||||||
|
mov sp, 8192 ; Set 'ss:sp' to the top of our 8K stack
|
||||||
|
|
||||||
|
; Set data segment to where we're loaded so we can implicitly access all 64K from here
|
||||||
|
mov ax, 0x7C0 ; Set 'ax' equal to the location of this bootloader divided by 16
|
||||||
|
mov ds, ax ; Set 'ds' to the this location
|
||||||
|
|
||||||
|
mov [disk_identifier], dl
|
||||||
|
; Print our message and stop execution
|
||||||
|
mov si, message ; Put address of the null-terminated string to output into 'si'
|
||||||
|
call print ; Call our string-printing routine
|
||||||
|
mov si, enter_debug_mode
|
||||||
|
call print
|
||||||
|
call printCRLF
|
||||||
|
; here goes wait call, for the user to enter debug mode.
|
||||||
|
; Wating for 2 seconds:
|
||||||
|
mov ah, 0x86 ; code for waiting interupt call
|
||||||
|
mov cx, 0x001e ; high count of microseconds
|
||||||
|
mov dx, 0x8480 ; low count
|
||||||
|
int 0x15
|
||||||
|
|
||||||
|
.busy_wait_for_key:
|
||||||
|
xor ax, ax
|
||||||
|
mov ah, 0x01 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
jnz debug_mode
|
||||||
|
|
||||||
|
; entering system check:
|
||||||
|
mov si, enter_system_check
|
||||||
|
|
||||||
|
mov si, sys_check_ok ; Put address of the null-terminated string to output into 'si'
|
||||||
|
call print ; Call our string-printing routine
|
||||||
|
|
||||||
|
mov si, boot_system ; Put address of the null-terminated string to output into 'si'
|
||||||
|
call print ; Call our string-printing routine
|
||||||
|
|
||||||
|
;This goes first as to now overwrite %ah and %al.
|
||||||
|
mov ax, 0x0
|
||||||
|
mov es, ax ;Section to write into
|
||||||
|
mov ah, 0x2 ;Read sectors from drive
|
||||||
|
mov al, 0xf ;Number of sectors to read (15 * 512 = 7680 bytes)
|
||||||
|
mov ch, 0x0 ;Low 8 bits of cylinder
|
||||||
|
mov cl, 0x11 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x0 ;Head number
|
||||||
|
mov dl, [disk_identifier] ;0x0 ;Drive number
|
||||||
|
mov bx, 0x7e00 ;Offset into section
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
;mov [0x7000], es ; saving retult of read
|
||||||
|
;
|
||||||
|
;Debug dump of loaded memory
|
||||||
|
;mov si, 500
|
||||||
|
;mov cx, 512
|
||||||
|
;call b_dumpmem
|
||||||
|
|
||||||
|
jnc notcarry
|
||||||
|
mov si, error_str
|
||||||
|
call print
|
||||||
|
jmp endcarrycheck
|
||||||
|
;
|
||||||
|
notcarry:
|
||||||
|
mov si, success_str
|
||||||
|
call print
|
||||||
|
call printCRLF
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
; xor ax, ax
|
||||||
|
; mov al, [disk_identifier]
|
||||||
|
; call dumpax
|
||||||
|
mov dl, [disk_identifier]
|
||||||
|
|
||||||
|
mov ax, 0x7e0
|
||||||
|
mov ds, ax
|
||||||
|
jmp 0x7e0:0x00
|
||||||
|
|
||||||
|
endcarrycheck:
|
||||||
|
cli ; Clear the Interrupt Flag (disable external interrupts)
|
||||||
|
hlt ; Halt the CPU (until the next external interrupt)
|
||||||
|
|
||||||
|
debug_mode:
|
||||||
|
mov si, .welcome_debug
|
||||||
|
call print
|
||||||
|
cli ; Clear the Interrupt Flag (disable external interrupts)
|
||||||
|
hlt
|
||||||
|
|
||||||
|
.welcome_debug db 'This is debug mode', 0
|
||||||
|
data:
|
||||||
|
message db 'Bootloader for SingOS! v0.0.3',13,10,0
|
||||||
|
enter_debug_mode db 'Press d to enter bootloader debug mode',13,10,0
|
||||||
|
enter_system_check db 'Performing system check:',13,10,0
|
||||||
|
sys_check_ok db 'System check ok', 13, 10, 0
|
||||||
|
boot_system db 'Read SingOS from disk', 13, 10, 0
|
||||||
|
error_str db 'Error', 0
|
||||||
|
success_str db 'Success', 0
|
||||||
|
disk_identifier db 0
|
||||||
|
|
||||||
|
; Routine for printing a 'ax' as hex
|
||||||
|
dumpax:
|
||||||
|
pusha ; save registers
|
||||||
|
mov bx, ax
|
||||||
|
mov ah, 0xE ; Teletype output
|
||||||
|
|
||||||
|
mov cx, 4 ; 4 nipples in a 16 bit word
|
||||||
|
.loop:
|
||||||
|
rol bx, 4 ; rotate to next nipple
|
||||||
|
mov al, bl ; we copy to al because we need to mask only the low 4 bits
|
||||||
|
and al, 1111b ; Do the masking
|
||||||
|
add al, '0' ; convert to ASCII
|
||||||
|
cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A'
|
||||||
|
jbe .skip ; -|-
|
||||||
|
add al, 7 ; -|-
|
||||||
|
.skip: ; -|-
|
||||||
|
int 0x10 ; BIOS call 'output'
|
||||||
|
loop .loop
|
||||||
|
|
||||||
|
popa ; restore registers
|
||||||
|
ret
|
||||||
|
|
||||||
|
dumpax10: ; Prints ax as 16-bit decimal number
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov bx, 10 ; Divisor
|
||||||
|
|
||||||
|
mov cx, 5 ; Loop 5 times
|
||||||
|
.loop1: ; finds digits and pushes them to stack
|
||||||
|
xor dx, dx
|
||||||
|
div bx
|
||||||
|
add dl, '0'
|
||||||
|
push dx
|
||||||
|
loop .loop1
|
||||||
|
|
||||||
|
|
||||||
|
mov ah, 0xE
|
||||||
|
mov cx, 5 ; Loop 5 times
|
||||||
|
mov bl, '0'
|
||||||
|
|
||||||
|
.loop2: ; Pops from stack until it hits a non-'0' value. It then jumps to nonzero_nopop to print it.
|
||||||
|
pop dx
|
||||||
|
mov al, dl
|
||||||
|
cmp al, bl
|
||||||
|
jne .nonzero_nopop
|
||||||
|
loop .loop2
|
||||||
|
|
||||||
|
.nonzero_loop: ; Pops values from the stack and prints them.
|
||||||
|
pop dx
|
||||||
|
mov al, dl
|
||||||
|
.nonzero_nopop: ; Part of the loop that prints the value. Jump to here to print without popping on first iteration.
|
||||||
|
int 0x10
|
||||||
|
loop .nonzero_loop
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
dumpax10_rev: ; Prints ax as 16-bit decimal number in reverse
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov cx, 10 ; Divisor
|
||||||
|
.loop:
|
||||||
|
xor dx, dx ; zero dx
|
||||||
|
div cx ; Divide dx:ax by 10 -> quotient in ax, remainder in dx
|
||||||
|
|
||||||
|
mov bx, ax ; save quotient in bx
|
||||||
|
|
||||||
|
mov al, dl ; put remainder in al
|
||||||
|
add al, '0' ; Make ASCII
|
||||||
|
|
||||||
|
mov ah, 0xE ; Set teletype output
|
||||||
|
int 0x10 ; BIOS: write one char
|
||||||
|
|
||||||
|
mov ax, bx
|
||||||
|
;test ax, ax
|
||||||
|
cmp ax, 0
|
||||||
|
jnz .loop
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
printCRLF:
|
||||||
|
mov ah, 0xE
|
||||||
|
mov al, 13
|
||||||
|
int 0x10
|
||||||
|
mov al, 10
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Routine for outputting string in 'si' register to screen
|
||||||
|
print:
|
||||||
|
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
|
||||||
|
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
|
||||||
|
.printchar:
|
||||||
|
lodsb ; Load byte at address SI into AL, and increment SI
|
||||||
|
cmp al, 0
|
||||||
|
je .done ; If the character is zero (NUL), stop writing the string
|
||||||
|
int 0x10 ; Otherwise, print the character via 'int 0x10'
|
||||||
|
jmp .printchar ; Repeat for the next character
|
||||||
|
.done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; b_dumpmem:
|
||||||
|
; push ax
|
||||||
|
; push dx
|
||||||
|
; call printCRLF
|
||||||
|
; shr cx, 1
|
||||||
|
; xor dx, dx ; zero dx
|
||||||
|
; .loop:
|
||||||
|
; cmp dx, cx
|
||||||
|
; jae .end
|
||||||
|
; mov ax, word [esi + 2*edx]
|
||||||
|
; call dumpax
|
||||||
|
; mov ax, 0xe20
|
||||||
|
; int 0x10
|
||||||
|
; inc dx
|
||||||
|
; jmp .loop
|
||||||
|
; .end:
|
||||||
|
; pop dx
|
||||||
|
; pop ax
|
||||||
|
; ret
|
||||||
|
; Pad to 510 bytes (boot sector size minus 2) with 0s, and finish with the two-byte standard boot signature
|
||||||
|
times 510-($-$$) db 0
|
||||||
|
dw 0xAA55 ; => 0x55 0xAA (little endian byte order)
|
||||||
|
; bootloder debug_mode goes here
|
||||||
|
|
||||||
|
times 8192-($-$$) db 0
|
||||||
|
|
||||||
|
; From Version 0.0.3 we are concatinate the bootloader and the kernel after compile time
|
||||||
|
;%include "kernel.nasm"
|
||||||
|
|
||||||
|
;times 8192-($-$$) db 0
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
if [ "$1" == "build" ] || [ "$1" == "run" ]; then
|
||||||
|
nasm -fbin bootloader.nasm -o bootloader.bin
|
||||||
|
nasm -fbin kernel.nasm -o kernel.bin
|
||||||
|
cat bootloader.bin kernel.bin > SingOS.img
|
||||||
|
|
||||||
|
if [ $1 == "run" ]; then
|
||||||
|
#qemu-system-x86_64 -drive format=raw,file=SingOS.img
|
||||||
|
#qemu-system-x86_64 -hda SingOS.img
|
||||||
|
qemu-system-x86_64 -drive index=0,if=floppy,format=raw,file=SingOS.img
|
||||||
|
else
|
||||||
|
bash -c "echo;echo;echo 'Press [ENTER] to exit'; read line"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Done"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ "$1" != "run" ]; then
|
||||||
|
nasm -fbin bootloader.nasm -o bootloader.bin
|
||||||
|
nasm -fbin kernel.nasm -o kernel.bin
|
||||||
|
cat bootloader.bin kernel.bin > SingOS.img
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" != "make" ]; then
|
||||||
|
#qemu-system-x86_64 -drive format=raw,file=SingOS.img
|
||||||
|
#qemu-system-x86_64 -hda SingOS.img
|
||||||
|
qemu-system-x86_64 -drive index=0,if=floppy,format=raw,file=SingOS.img
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Done"
|
||||||
|
|
||||||
+305
@@ -0,0 +1,305 @@
|
|||||||
|
BITS 16
|
||||||
|
|
||||||
|
start_sing:
|
||||||
|
; loading essentials for SingOS to run
|
||||||
|
|
||||||
|
; VSFS is loaded:
|
||||||
|
mov [global_disk_identifier], dl ; saving disk_identifier, this is the number the disk that we are booting from.
|
||||||
|
; This number is set by the bios
|
||||||
|
|
||||||
|
jmp sing_ready
|
||||||
|
%include "mem_lib/mem_lib.nasm"
|
||||||
|
%include "lib/os_lib.nasm"
|
||||||
|
%include "lib/string.nasm"
|
||||||
|
%include "lib/debug_tools.nasm"
|
||||||
|
%include "lib/std_power.nasm"
|
||||||
|
%include "lib/svim.nasm"
|
||||||
|
%include "vsfs/vsfs.nasm"
|
||||||
|
%include "CLI/CLI.nasm"
|
||||||
|
|
||||||
|
sing_ready: ; SingOS is ready for the user:
|
||||||
|
|
||||||
|
call os_clear_screen
|
||||||
|
|
||||||
|
mov si, welcome ; Put address of the null-terminated string to output into 'si'
|
||||||
|
call print ; Call our string-printing routine
|
||||||
|
|
||||||
|
print_format example_format_string, 0xdead, 0xbeef, 0xbabe, 420
|
||||||
|
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
call dump_general_registers
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
call dump_segment_registers
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
call dump_stack_registers
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
call dump_status_flags
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
call print_help_message
|
||||||
|
|
||||||
|
; call dump_status_flags
|
||||||
|
; call printCRLF
|
||||||
|
|
||||||
|
mov si, command_line
|
||||||
|
call print
|
||||||
|
jmp terminal
|
||||||
|
terminal:
|
||||||
|
call wait_for_key
|
||||||
|
jmp terminal
|
||||||
|
|
||||||
|
wait_for_key:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov ax, 0
|
||||||
|
mov ah, 0x10 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
|
||||||
|
cmp ax, 0x11b; ESC key
|
||||||
|
je near .end
|
||||||
|
cmp ax, 0x3b00 ; f1 key
|
||||||
|
je .change_one
|
||||||
|
cmp ax, 0x3c00 ; f2 key
|
||||||
|
je .change_two
|
||||||
|
cmp ax, 0x1c0d ; enter key
|
||||||
|
je .enter_hit
|
||||||
|
mov [.tmp_buf], ax ; save the key pressed befor printing it
|
||||||
|
|
||||||
|
mov cx, [.tmp_buf]
|
||||||
|
cmp cx, 0x0e08 ; backspace key
|
||||||
|
;je .backspace_handler
|
||||||
|
jne .dont_backspace
|
||||||
|
call CLI_DELETE
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.dont_backspace:
|
||||||
|
call CLI_ASCII_INPUT
|
||||||
|
|
||||||
|
;mov ah, 0xE ; This destroy the high part of the key pressed
|
||||||
|
;mov bl, 0x02
|
||||||
|
;int 0x10
|
||||||
|
;mov bx, [.os_command_buffer_counter]
|
||||||
|
;cmp bx, 254
|
||||||
|
;je .os_buffer_full
|
||||||
|
;mov ax, bx
|
||||||
|
;add ax, .os_command_buffer
|
||||||
|
;add bx, 0x01
|
||||||
|
;mov [.os_command_buffer_counter], bx
|
||||||
|
;mov bx, ax
|
||||||
|
;mov ax, [.tmp_buf]
|
||||||
|
;mov [bx], ax
|
||||||
|
.return_enter:
|
||||||
|
mov ax, [.tmp_buf]
|
||||||
|
popa ; But restore all other regs
|
||||||
|
ret
|
||||||
|
|
||||||
|
.os_buffer_full:
|
||||||
|
mov si, .os_str_full
|
||||||
|
call print
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.backspace_handler:
|
||||||
|
; bx already set to the current buffer count
|
||||||
|
mov bx, [.os_command_buffer_counter]
|
||||||
|
cmp bx, 0x00
|
||||||
|
je .backspace_stop
|
||||||
|
sub bx, 0x01
|
||||||
|
mov [.os_command_buffer_counter], bx
|
||||||
|
add bx, .os_command_buffer
|
||||||
|
mov ax, 0x00
|
||||||
|
mov [bx], ax
|
||||||
|
mov ax, [.tmp_buf] ; load the backpace
|
||||||
|
mov ah, 0xE ; print the backspace
|
||||||
|
int 0x10
|
||||||
|
mov al, 0
|
||||||
|
int 0x10
|
||||||
|
mov al, 0x08
|
||||||
|
int 0x10
|
||||||
|
;mov al, 0x20 ; now the curser is one back
|
||||||
|
;int 0x10 ; print null charecter
|
||||||
|
.backspace_stop:
|
||||||
|
popa ; But restore all other regs
|
||||||
|
ret
|
||||||
|
|
||||||
|
.change_one:
|
||||||
|
|
||||||
|
mov al, 0x00 ; arg: index 0
|
||||||
|
call os_change_screen
|
||||||
|
jmp terminal
|
||||||
|
|
||||||
|
.change_two:
|
||||||
|
|
||||||
|
mov al, 0x01 ; arg: index 0
|
||||||
|
call os_change_screen
|
||||||
|
jmp terminal
|
||||||
|
|
||||||
|
|
||||||
|
.enter_hit:
|
||||||
|
call CLI_CONFIRM_INPUT
|
||||||
|
jmp .command_interpreter
|
||||||
|
|
||||||
|
.no_str:
|
||||||
|
mov si, command_line
|
||||||
|
call print
|
||||||
|
jmp .return_enter
|
||||||
|
|
||||||
|
.compare_with_LIST_searchindex dw 0
|
||||||
|
.compare_with_LIST_NAMES dw .compare_with_dumpmem, .compare_with_keyprint, .compare_with_display, .compare_with_svim, .compare_with_clear, .compare_with_ls, 0
|
||||||
|
.compare_with_LIST_POINTERS dw dumpmem, keyprint, .change_display, svim, .clearcommand, vsfs_list_files_command, 0
|
||||||
|
.compare_with_dumpmem db 'dumpmem', 0
|
||||||
|
.compare_with_keyprint db 'keyprint', 0
|
||||||
|
.compare_with_display db 'display', 0 ; original this is the display command for better grapichs
|
||||||
|
.compare_with_svim db 'svim', 0 ; SingOS vim edition 'svim'
|
||||||
|
.compare_with_clear db 'clear', 0 ; Clear the screen
|
||||||
|
.compare_with_ls db 'ls', 0 ; List file table
|
||||||
|
|
||||||
|
.end:
|
||||||
|
mov si, exit_message
|
||||||
|
call print
|
||||||
|
|
||||||
|
call power_off
|
||||||
|
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
.change_display:
|
||||||
|
mov ax, 0x4F02 ; set VBE mode
|
||||||
|
mov bx, 0x4118 ; VBE mode number; notice that bits 0-13 contain the mode number and bit 14 (LFB) is set and bit 15 (DM) is clear.
|
||||||
|
;xor bx, bx
|
||||||
|
;xor cx, cx
|
||||||
|
;xor dx, dx
|
||||||
|
;mov ah, 0x06
|
||||||
|
;mov al, 0xff
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
.clearcommand:
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx ; Upper and left coordinate
|
||||||
|
mov bh, 0x0f ; color for new screen 0 = black f = white
|
||||||
|
mov dh, 0xff ; Select all screen
|
||||||
|
mov dl, 0xff ; Select all screen
|
||||||
|
mov ah, 0x07 ; scrool down
|
||||||
|
mov al, 0x00 ; scrool 0 lines (means blank screen )
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; move curser back to the top of the screen
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x00 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
.tmp_buf dw 0
|
||||||
|
.os_command_buffer times 255 dw 0
|
||||||
|
.os_command_buffer_counter dw 0
|
||||||
|
.os_str_full db 13, 10, 'Buffer is full', 13, 10, 0
|
||||||
|
|
||||||
|
.command_interpreter:
|
||||||
|
|
||||||
|
mov bx, [.os_command_buffer_counter]
|
||||||
|
cmp bx, 0x00
|
||||||
|
je near .no_str ; First byte is 0 => No command
|
||||||
|
call printCRLF
|
||||||
|
add bx, .os_command_buffer ; Note addition. Sets bx to the end of the string, which should be guaranteed to be 0
|
||||||
|
mov ax, 0x00
|
||||||
|
mov [bx], ax ; Ensure that the command is null-terminated
|
||||||
|
xor bx, bx
|
||||||
|
mov [.os_command_buffer_counter], bx
|
||||||
|
mov si, .os_command_buffer
|
||||||
|
call print ; Echo the command
|
||||||
|
|
||||||
|
lea si, [.os_command_buffer]
|
||||||
|
;mov dword [.compare_with_LIST_searchindex], 0 ; Next time, start at 0
|
||||||
|
mov cx, 0 ; Index
|
||||||
|
|
||||||
|
.command_interpreter_searchloop:
|
||||||
|
;call printCRLF
|
||||||
|
;mov ax, cx
|
||||||
|
;call dumpax
|
||||||
|
;mov bx, [.compare_with_LIST_searchindex]
|
||||||
|
mov bx, cx
|
||||||
|
add bx, bx ; The pointers are 2 bytes long. Compensate here
|
||||||
|
|
||||||
|
;call printCRLF
|
||||||
|
;mov ax, cx
|
||||||
|
;call dumpax
|
||||||
|
|
||||||
|
mov dx, [.compare_with_LIST_NAMES+bx] ; Here it HAS to be bx. Otherwise it is invalid for some reason
|
||||||
|
mov bx, dx
|
||||||
|
|
||||||
|
lea di, [bx]
|
||||||
|
|
||||||
|
call stringcompare
|
||||||
|
|
||||||
|
je .command_interpreter_foundcommand
|
||||||
|
|
||||||
|
; I don't assume here that the registers contain the same values they used to after the calls
|
||||||
|
;mov bx, [.compare_with_LIST_searchindex]
|
||||||
|
;inc bx
|
||||||
|
;mov [.compare_with_LIST_searchindex], bx
|
||||||
|
inc cx
|
||||||
|
|
||||||
|
mov bx, cx
|
||||||
|
add bx, bx
|
||||||
|
mov dx, [.compare_with_LIST_NAMES+bx]
|
||||||
|
|
||||||
|
cmp dx, 0 ;Is it at the null terminator?
|
||||||
|
|
||||||
|
jne .command_interpreter_searchloop ; There is another command to check
|
||||||
|
|
||||||
|
jmp .no_str
|
||||||
|
|
||||||
|
.command_interpreter_foundcommand:
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
;mov bx, [.compare_with_LIST_searchindex] ; Remember this thing
|
||||||
|
mov bx, cx
|
||||||
|
add bx, bx ;The pointers are 2 bytes long. Compensate here
|
||||||
|
|
||||||
|
;call printCRLF
|
||||||
|
;mov ax, cx
|
||||||
|
;call dumpax
|
||||||
|
|
||||||
|
mov dx, [.compare_with_LIST_POINTERS+bx] ; This is where the program is.
|
||||||
|
|
||||||
|
;mov ax, dx
|
||||||
|
;call printCRLF
|
||||||
|
;call dumpax
|
||||||
|
|
||||||
|
call dx
|
||||||
|
|
||||||
|
jmp .no_str
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
global_vars:
|
||||||
|
global_vsfs_master_record dw 8 ; this is the index of the start of the master table for the filesystem
|
||||||
|
; This should maby contain more information.
|
||||||
|
; and somehow be setted in a fix sector, which holds all the variabels for SingOS
|
||||||
|
; 8 is currently the magic number where the file system starts on our disk.
|
||||||
|
|
||||||
|
global_vsfs_next_index dw 0 ; This is the next index to the next file created.
|
||||||
|
; this var is set durling load of SingOS
|
||||||
|
; Changed my mind, the index is currently loaded and written back to disk under
|
||||||
|
; creation of a new file.
|
||||||
|
global_disk_identifier db 0 ; set by the bios passed by the bootloader,
|
||||||
|
; this is the bios ID
|
||||||
|
|
||||||
|
data:
|
||||||
|
welcome db "###############################################################################", 13, 10, "# Welcome to SingOS anniversary edition. #", 13, 10, "# This build marks 1 year of SingOS! #", 13, 10, "###############################################################################", 13, 10, 'Press ESC to halt.', 13, 10, 13, 10, 0
|
||||||
|
exit_message db 13, 10, 'Goodbye from SingOS',13,10,'The system has halted.', 0
|
||||||
|
command_line db 13, 10, 'groot@SingOS $ ', 0
|
||||||
|
number_one_zstring db '71', 0
|
||||||
|
example_format_string db "(%x-%x-%x){%d%%}",0
|
||||||
|
|
||||||
|
;times 131072-($-$$) db 0 ; 256 sectos
|
||||||
|
;GLOBAL_VSFS_START db 'VSFS v0.1' ; sector 257 reserved for file system information
|
||||||
|
times (1<<20)-($-$$) db 0 ; sector 258 to sector 2048 should be avaliable to the filesystem.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
SingOs
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Folder of compiling the OS
|
||||||
|
This folder has to be empty on the repository
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
as sing_boot_alt.s -o ../compile_folder/alt.o
|
||||||
|
ld -Ttext 0x7c00 --oformat=binary ../compile_folder/alt.o -o ../compile_folder/sing.bin
|
||||||
|
dd if=../compile_folder/sing.bin of=../compile_folder/sing.img
|
||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
as $1.s -o ../compile_folder/$2.o
|
||||||
|
ld -Ttext 0x7c00 --oformat=binary ../compile_folder/$2.o -o ../compile_folder/$2.bin
|
||||||
|
dd if=../compile_folder/$2.bin of=../compile_folder/$2.img
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
|
||||||
|
|
||||||
|
http://www.computer-engineering.org/index.html // keyboard and mouse programming
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#generate 16-bit code
|
||||||
|
.code16
|
||||||
|
|
||||||
|
#hint the assembler that here is the executable code located
|
||||||
|
.text
|
||||||
|
.globl _start;
|
||||||
|
#boot code entry
|
||||||
|
_start:
|
||||||
|
jmp _boot
|
||||||
|
start: .asciz "Start.\n\r"
|
||||||
|
error: .asciz "Error.\n\r"
|
||||||
|
succes: .asciz "Succes.\n\r"
|
||||||
|
ffs: .asciz "F.\n\r"
|
||||||
|
end: .asciz "End.\n\r"
|
||||||
|
|
||||||
|
.macro mWriteString str #macro which calls a function to print a string
|
||||||
|
leaw \str, %si
|
||||||
|
call .writeStringIn
|
||||||
|
.endm
|
||||||
|
|
||||||
|
# function to print the string
|
||||||
|
.writeStringIn:
|
||||||
|
lodsb
|
||||||
|
orb %al, %al
|
||||||
|
jz .writeStringOut
|
||||||
|
movb $0x0e, %ah
|
||||||
|
int $0x10
|
||||||
|
jmp .writeStringIn
|
||||||
|
.writeStringOut:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
_boot:
|
||||||
|
mWriteString start
|
||||||
|
|
||||||
|
#This goes first as to now overwrite %ah and %al.
|
||||||
|
mov $0x00, %ax
|
||||||
|
mov %ax, %es #Section to write into
|
||||||
|
|
||||||
|
mov $0x02, %ah # Read sectors from drive
|
||||||
|
mov $0x01, %al # Number of sectors to read
|
||||||
|
mov $0x00, %ch # Low 8 bits of cylinder
|
||||||
|
mov $0x02, %cl # First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov $0x00, %dh # Head number
|
||||||
|
mov $0x00, %dl # Drive number
|
||||||
|
# mov $0x00, %es
|
||||||
|
mov $0xFF, %bx #Offset into section
|
||||||
|
int $0x13 # Low level disk services
|
||||||
|
|
||||||
|
jnc notcarry
|
||||||
|
mWriteString error
|
||||||
|
jmp endcarrycheck
|
||||||
|
|
||||||
|
notcarry:
|
||||||
|
mWriteString succes
|
||||||
|
#fallthrough
|
||||||
|
|
||||||
|
endcarrycheck:
|
||||||
|
|
||||||
|
mWriteString mystr
|
||||||
|
|
||||||
|
mWriteString end
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#move to 510th byte from the start and append boot signature
|
||||||
|
. = _start + 510
|
||||||
|
.byte 0x55
|
||||||
|
.byte 0xaa
|
||||||
|
|
||||||
|
mystr: .asciz "asdf"
|
||||||
|
|
||||||
|
. = _start + 1023
|
||||||
|
.byte 0x00
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
#generate 16-bit code
|
||||||
|
.code16
|
||||||
|
|
||||||
|
#hint the assembler that here is the executable code located
|
||||||
|
.text
|
||||||
|
.globl _start;
|
||||||
|
#boot code entry
|
||||||
|
_start:
|
||||||
|
jmp _boot
|
||||||
|
start: .asciz "Start.\n\r"
|
||||||
|
error: .asciz "Error.\n\r"
|
||||||
|
succes: .asciz "Succes.\n\r"
|
||||||
|
ffs: .asciz "F.\n\r"
|
||||||
|
end: .asciz "End.\n\r"
|
||||||
|
derpy2str: .asciz "This is from derpy2.\n\r"
|
||||||
|
cookies: .word derpy2
|
||||||
|
|
||||||
|
.macro mWriteString str #macro which calls a function to print a string
|
||||||
|
leaw \str, %si
|
||||||
|
call .writeStringIn
|
||||||
|
.endm
|
||||||
|
|
||||||
|
# function to print the string
|
||||||
|
.writeStringIn:
|
||||||
|
lodsb
|
||||||
|
orb %al, %al
|
||||||
|
jz .writeStringOut
|
||||||
|
movb $0x0e, %ah
|
||||||
|
int $0x10
|
||||||
|
jmp .writeStringIn
|
||||||
|
.writeStringOut:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
_boot:
|
||||||
|
mWriteString start
|
||||||
|
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'X', %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
movb $'\n', %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
movb $'\r', %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
lgdt gdtdesc
|
||||||
|
|
||||||
|
#movb $42, %bl #NOT 'A'
|
||||||
|
#movb %bl, 0x512
|
||||||
|
|
||||||
|
#This goes first as to now overwrite %ah and %al.
|
||||||
|
mov $0x00, %ax
|
||||||
|
#mov $0x08, %ax
|
||||||
|
mov %ax, %es #Section to write into
|
||||||
|
|
||||||
|
mov $0x02, %ah # Read sectors from drive
|
||||||
|
mov $0x01, %al # Number of sectors to read
|
||||||
|
mov $0x00, %ch # Low 8 bits of cylinder
|
||||||
|
mov $0x02, %cl # First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov $0x00, %dh # Head number
|
||||||
|
mov $0x00, %dl # Drive number
|
||||||
|
# mov $0x00, %es
|
||||||
|
#mov $0x7e00, %bx #Offset into section
|
||||||
|
mov $(_start+0x200), %bx #Offset into section
|
||||||
|
#mov $0x0, %bx #Offset into section
|
||||||
|
int $0x13 # Low level disk services
|
||||||
|
|
||||||
|
jnc notcarry
|
||||||
|
#mWriteString error
|
||||||
|
jmp endcarrycheck
|
||||||
|
|
||||||
|
notcarry:
|
||||||
|
#mWriteString succes
|
||||||
|
|
||||||
|
#mov $0x7000, %ax
|
||||||
|
#movb (%ax), %bl
|
||||||
|
#movb %bl, ffs
|
||||||
|
#movb 0x7000, %bl
|
||||||
|
#movb %bl, ffs
|
||||||
|
#mWriteString ffs
|
||||||
|
#fallthrough
|
||||||
|
|
||||||
|
endcarrycheck:
|
||||||
|
|
||||||
|
#mWriteString mystr-block2_offset
|
||||||
|
#mWriteString 0x513
|
||||||
|
#mWriteString mystr
|
||||||
|
|
||||||
|
#ljmp $0x0, $derpy
|
||||||
|
#.byte 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
#ljmp $0x00, $0x7e00
|
||||||
|
#ljmp $0x00, $derpy2
|
||||||
|
ljmp $0x00, $code
|
||||||
|
|
||||||
|
# movw $derpy, %ax
|
||||||
|
#
|
||||||
|
# cmp $0x7e00, %ax
|
||||||
|
# je equal
|
||||||
|
# mWriteString error
|
||||||
|
# jmp after
|
||||||
|
#
|
||||||
|
# equal:
|
||||||
|
# mWriteString succes
|
||||||
|
#
|
||||||
|
# after:
|
||||||
|
/*
|
||||||
|
movb $0x0e, %ah
|
||||||
|
|
||||||
|
movw $derpy, %cx
|
||||||
|
|
||||||
|
movb 0x0e, %ah
|
||||||
|
movb $'I', %al
|
||||||
|
int $0x10
|
||||||
|
movb 0x0e, %ah
|
||||||
|
movb $'J', %al
|
||||||
|
int $0x10
|
||||||
|
*/
|
||||||
|
|
||||||
|
#movw $0x7E00, %cx
|
||||||
|
movw $derpy2, %cx
|
||||||
|
|
||||||
|
movb $0x0e, %ah
|
||||||
|
#movb $'Y', %al
|
||||||
|
movb %ch, %al
|
||||||
|
#movb $'H', %al
|
||||||
|
#movb $0x7E, %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
movb $0x0e, %ah
|
||||||
|
#movb $'Z', %al
|
||||||
|
movb %cl, %al
|
||||||
|
#add $0x7E, %al
|
||||||
|
#sub $0x50, %al
|
||||||
|
#movb $0x3C, %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'\n', %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'\r', %al
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
|
||||||
|
#mWriteString mystr
|
||||||
|
|
||||||
|
#jmp derpy
|
||||||
|
derpyret:
|
||||||
|
|
||||||
|
mWriteString end
|
||||||
|
|
||||||
|
#jmp 0x7008
|
||||||
|
#endend:
|
||||||
|
#mWriteString end
|
||||||
|
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
derpy:
|
||||||
|
mWriteString ffs
|
||||||
|
ljmp $0x00, $derpyret
|
||||||
|
#jmp derpyret
|
||||||
|
|
||||||
|
.p2align 2 /* force 4-byte alignment */
|
||||||
|
gdt:
|
||||||
|
.word 0, 0
|
||||||
|
.byte 0, 0, 0, 0
|
||||||
|
|
||||||
|
/* code segment */
|
||||||
|
.word 0xFFFF, 0
|
||||||
|
.byte 0, 0x9A, 0xCF, 0
|
||||||
|
|
||||||
|
/* data segment */
|
||||||
|
.word 0xFFFF, 0
|
||||||
|
.byte 0, 0x92, 0xCF, 0
|
||||||
|
|
||||||
|
/* 16 bit real mode CS */
|
||||||
|
.word 0xFFFF, 0
|
||||||
|
.byte 0, 0x9E, 0, 0
|
||||||
|
|
||||||
|
/* 16 bit real mode DS */
|
||||||
|
.word 0xFFFF, 0
|
||||||
|
.byte 0, 0x92, 0, 0
|
||||||
|
|
||||||
|
/* this is the GDT descriptor */
|
||||||
|
gdtdesc:
|
||||||
|
.word 0x27 /* limit */
|
||||||
|
.long gdt /* addr */
|
||||||
|
|
||||||
|
#move to 510th byte from the start and append boot signature
|
||||||
|
. = _start + 510
|
||||||
|
.byte 0x55
|
||||||
|
.byte 0xaa
|
||||||
|
#block2_offset:
|
||||||
|
.byte 'A' #Byte 513
|
||||||
|
#mystr: .asciz "asdf\n\r"
|
||||||
|
|
||||||
|
#derpderp:
|
||||||
|
# mwriteString 0x7001
|
||||||
|
# jmp endend
|
||||||
|
|
||||||
|
derpy2:
|
||||||
|
mWriteString derpy2str
|
||||||
|
ljmp $0x00, $derpyret
|
||||||
|
|
||||||
|
code:
|
||||||
|
mWriteString derpy2str
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'C', %al
|
||||||
|
int $0x10
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'\n', %al
|
||||||
|
int $0x10
|
||||||
|
movb $0x0e, %ah
|
||||||
|
movb $'\r', %al
|
||||||
|
int $0x10
|
||||||
|
ljmp $0x00, $derpyret
|
||||||
|
|
||||||
|
. = _start + 1021
|
||||||
|
.byte 0x00
|
||||||
|
|
||||||
|
.word derpy2
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
#generate 16-bit code
|
||||||
|
.code16
|
||||||
|
|
||||||
|
#hint the assembler that here is the executable code located
|
||||||
|
.text
|
||||||
|
.globl _start;
|
||||||
|
#boot code entry
|
||||||
|
_start:
|
||||||
|
jmp _boot #jump to boot code
|
||||||
|
welcome: .asciz "Hello, new World\n\r" #here we define the string
|
||||||
|
enter_number: .asciz "Enter a number: \n\r"
|
||||||
|
lower_msg: .asciz "\nYour number is to low :( \n\r" # 26
|
||||||
|
higher_msg: .asciz "\nYour number is to high :( \n\r" # 27
|
||||||
|
winner_msg: .asciz "\nYour are the CAMPION, :D \n\r" # 26
|
||||||
|
|
||||||
|
.macro mWriteString str #macro which calls a function to print a string
|
||||||
|
leaw \str, %si
|
||||||
|
call .writeStringIn
|
||||||
|
.endm
|
||||||
|
|
||||||
|
# function to print the string
|
||||||
|
.writeStringIn:
|
||||||
|
lodsb
|
||||||
|
orb %al, %al
|
||||||
|
jz .writeStringOut
|
||||||
|
movb $0x0e, %ah
|
||||||
|
int $0x10
|
||||||
|
jmp .writeStringIn
|
||||||
|
.writeStringOut:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.type get_number, @function
|
||||||
|
get_number:
|
||||||
|
|
||||||
|
# save state before function
|
||||||
|
push %bp
|
||||||
|
mov %sp, %bp
|
||||||
|
|
||||||
|
push %bx
|
||||||
|
push %cx
|
||||||
|
# Start of function
|
||||||
|
mWriteString enter_number
|
||||||
|
|
||||||
|
mov $0, %ah
|
||||||
|
mov $0, %al
|
||||||
|
int $0x16
|
||||||
|
|
||||||
|
mov $0x0E, %ah
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
pop %cx
|
||||||
|
pop %bx
|
||||||
|
|
||||||
|
mov %bp, %sp
|
||||||
|
pop %bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.type string_to_int, @function
|
||||||
|
string_to_int:
|
||||||
|
/* Converts a string to an integer. Returns the integer in %rax.
|
||||||
|
* %rax: Address of string to convert.
|
||||||
|
*/
|
||||||
|
push %bp
|
||||||
|
mov %sp, %bp
|
||||||
|
|
||||||
|
push %bx
|
||||||
|
push %cx
|
||||||
|
|
||||||
|
mov %ax, %dx
|
||||||
|
|
||||||
|
cmp $47, %dx
|
||||||
|
jl not_a_num
|
||||||
|
cmp $57, %dx
|
||||||
|
jg not_a_num
|
||||||
|
# I multiply by 10 to shift the number one placement to the right to add the newest integer.
|
||||||
|
sub $48, %dx
|
||||||
|
jmp convertdone # In ascii, numbers start at 0 = 48, 1 = 49, 2 = 50 and so on. So I subtract 48 to get the digit.
|
||||||
|
|
||||||
|
not_a_num:
|
||||||
|
xor %dx, %dx
|
||||||
|
|
||||||
|
convertdone:
|
||||||
|
|
||||||
|
pop %cx
|
||||||
|
pop %bx
|
||||||
|
|
||||||
|
mov %bp, %sp
|
||||||
|
pop %bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
_boot:
|
||||||
|
mWriteString welcome
|
||||||
|
|
||||||
|
guess:
|
||||||
|
call get_number
|
||||||
|
xor %ah, %ah
|
||||||
|
call string_to_int
|
||||||
|
|
||||||
|
cmp $5, %dx
|
||||||
|
|
||||||
|
jl if_lower
|
||||||
|
je if_eg
|
||||||
|
jg if_higher
|
||||||
|
|
||||||
|
if_lower:
|
||||||
|
mWriteString lower_msg
|
||||||
|
jmp guess
|
||||||
|
|
||||||
|
if_higher:
|
||||||
|
mWriteString higher_msg
|
||||||
|
jmp guess
|
||||||
|
|
||||||
|
if_eg:
|
||||||
|
mWriteString winner_msg
|
||||||
|
|
||||||
|
#move to 510th byte from the start and append boot signature
|
||||||
|
. = _start + 510
|
||||||
|
.byte 0x55
|
||||||
|
.byte 0xaa
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
#generate 16-bit code
|
||||||
|
.code16
|
||||||
|
|
||||||
|
#hint the assembler that here is the executable code located
|
||||||
|
.text
|
||||||
|
.globl _start;
|
||||||
|
#boot code entry
|
||||||
|
_start:
|
||||||
|
welcome: .asciz "Welcome to this very fine Guessing game \n\r" #here we define the string
|
||||||
|
enter_number: .asciz "Enter a number: \n"
|
||||||
|
lower_msg: .asciz "Your number is to low :( \n" # 26
|
||||||
|
higher_msg: .asciz "Your number is to high :( \n" # 27
|
||||||
|
winner_msg: .asciz "Your are the CAMPION, :D \n" # 26
|
||||||
|
.macro mWriteString str #macro which calls a function to print a string
|
||||||
|
leaw \str, %si
|
||||||
|
call .writeStringIn
|
||||||
|
.endm
|
||||||
|
#jmp _boot
|
||||||
|
|
||||||
|
# function to print the string
|
||||||
|
.writeStringIn:
|
||||||
|
lodsb
|
||||||
|
orb %al, %al
|
||||||
|
jz .writeStringOut
|
||||||
|
movb $0x0e, %ah
|
||||||
|
int $0x10
|
||||||
|
jmp .writeStringIn
|
||||||
|
.writeStringOut:
|
||||||
|
ret #jump to boot code
|
||||||
|
|
||||||
|
mWriteString welcome
|
||||||
|
|
||||||
|
/*
|
||||||
|
guess:
|
||||||
|
call get_number
|
||||||
|
xor %ah, %ah
|
||||||
|
call string_to_int
|
||||||
|
|
||||||
|
cmp $5, %dx
|
||||||
|
|
||||||
|
jl if_lower # rax less then 50
|
||||||
|
je if_eg
|
||||||
|
jg if_higher
|
||||||
|
if_lower:
|
||||||
|
mWriteString lower_msg
|
||||||
|
jmp guess
|
||||||
|
|
||||||
|
if_higher:
|
||||||
|
mWriteString higher_msg
|
||||||
|
jmp guess
|
||||||
|
|
||||||
|
if_eg:
|
||||||
|
mWriteString winner_msg #message length
|
||||||
|
|
||||||
|
hlt
|
||||||
|
*/
|
||||||
|
#_boot:
|
||||||
|
# mWriteString welcome
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#.type string_to_int, @function
|
||||||
|
#string_to_int:
|
||||||
|
/* Converts a string to an integer. Returns the integer in %rax.
|
||||||
|
* %rax: Address of string to convert.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
push %bp
|
||||||
|
mov %sp, %bp
|
||||||
|
|
||||||
|
push %bx
|
||||||
|
push %cx
|
||||||
|
|
||||||
|
mov %ax, %dx
|
||||||
|
|
||||||
|
xor %ax, %ax
|
||||||
|
|
||||||
|
cmp $47, %dx
|
||||||
|
jl not_a_num
|
||||||
|
cmp $57, %dx
|
||||||
|
jg not_a_num
|
||||||
|
# I multiply by 10 to shift the number one placement to the right to add the newest integer.
|
||||||
|
sub $48, %dx # In ascii, numbers start at 0 = 48, 1 = 49, 2 = 50 and so on. So I subtract 48 to get the digit.
|
||||||
|
|
||||||
|
not_a_num:
|
||||||
|
xor %dx, %dx
|
||||||
|
|
||||||
|
convertdone:
|
||||||
|
|
||||||
|
pop %cx
|
||||||
|
pop %bx
|
||||||
|
|
||||||
|
mov %bp, %sp
|
||||||
|
pop %bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
.type get_number, @function
|
||||||
|
get_number:
|
||||||
|
# .enter_char:
|
||||||
|
# mov $0, %ah
|
||||||
|
# mov $0, %al
|
||||||
|
# int $0x16
|
||||||
|
|
||||||
|
# mov $0x0E, %ah
|
||||||
|
# int $0x10
|
||||||
|
|
||||||
|
# jmp .enter_char
|
||||||
|
|
||||||
|
# save state before function
|
||||||
|
push %bp
|
||||||
|
mov %sp, %bp
|
||||||
|
|
||||||
|
push %bx
|
||||||
|
push %cx
|
||||||
|
# Start of function
|
||||||
|
mWriteString enter_number
|
||||||
|
|
||||||
|
mov $0, %ah
|
||||||
|
mov $0, %al
|
||||||
|
int $0x16
|
||||||
|
|
||||||
|
mov $0x0E, %ah
|
||||||
|
int $0x10
|
||||||
|
|
||||||
|
pop %cx
|
||||||
|
pop %bx
|
||||||
|
|
||||||
|
mov %bp, %sp
|
||||||
|
pop %bp
|
||||||
|
ret
|
||||||
|
*/
|
||||||
|
#move to 510th byte from the start and append boot signature
|
||||||
|
. = _start + 510
|
||||||
|
.byte 0x55
|
||||||
|
.byte 0xaa
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
%macro print_format 1
|
||||||
|
lea si, [%1]
|
||||||
|
call _print_format
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 2
|
||||||
|
lea si, [%1]
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 2
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 3
|
||||||
|
lea si, [%1]
|
||||||
|
push %3
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 4
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 4
|
||||||
|
lea si, [%1]
|
||||||
|
push %4
|
||||||
|
push %3
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 6
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 5
|
||||||
|
lea si, [%1]
|
||||||
|
push %5
|
||||||
|
push %4
|
||||||
|
push %3
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 8
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 6
|
||||||
|
lea si, [%1]
|
||||||
|
push %6
|
||||||
|
push %5
|
||||||
|
push %4
|
||||||
|
push %3
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 10
|
||||||
|
%endmacro
|
||||||
|
%macro print_format 7
|
||||||
|
lea si, [%1]
|
||||||
|
push %7
|
||||||
|
push %6
|
||||||
|
push %5
|
||||||
|
push %4
|
||||||
|
push %3
|
||||||
|
push %2
|
||||||
|
call _print_format
|
||||||
|
add sp, 12
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
|
||||||
|
BITS 16
|
||||||
|
|
||||||
|
dumpmem_hardcoded_args:
|
||||||
|
mov si, sp
|
||||||
|
mov si, [si]
|
||||||
|
mov cx, 400
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dumpmem:
|
||||||
|
; Dumps memory
|
||||||
|
; IN 'si': Start address to dump from
|
||||||
|
; IN 'cx': Number of bytes do dump
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
pusha
|
||||||
|
|
||||||
|
xor edx, edx
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
mov ax, word [esi + 2*edx]
|
||||||
|
inc edx
|
||||||
|
call dumpax
|
||||||
|
mov ax, (0xE<<8)|' ' ; print space
|
||||||
|
int 0x10
|
||||||
|
loop .loop
|
||||||
|
.end:
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dumpax:
|
||||||
|
; Prints the contens of ax as a hexadecimal number
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
pusha ; save registers
|
||||||
|
mov dx, ax
|
||||||
|
mov ah, 0xE ; Teletype output
|
||||||
|
|
||||||
|
mov cx, 4 ; 4 nibbles in a 16 bit word
|
||||||
|
.print_loop:
|
||||||
|
rol dx, 4 ; rotate to next nibble
|
||||||
|
mov al, dl ; we copy to al because we need to mask only the low 4 bits
|
||||||
|
and al, 0xF ; Do the masking
|
||||||
|
add al, '0' ; convert to ASCII
|
||||||
|
|
||||||
|
; If we are greater than 9 ascii...
|
||||||
|
cmp al, '9'
|
||||||
|
jbe .skip_diff_to_ascii_A
|
||||||
|
add al, 'A'-('9'+1) ; ...add 7 to make digits 10 to 15 be represented as 'A' to 'F'
|
||||||
|
.skip_diff_to_ascii_A:
|
||||||
|
|
||||||
|
int 0x10 ; BIOS call 'output'
|
||||||
|
loop .print_loop
|
||||||
|
|
||||||
|
popa ; restore registers
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dumpax10:
|
||||||
|
; Prints the contens of ax as a decimal number
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov bx, 10 ; Divisor
|
||||||
|
|
||||||
|
xor cx, cx ; Digit count starts at 0
|
||||||
|
|
||||||
|
.loop_divide: ; finds digits and pushes them to stack
|
||||||
|
test ax, ax
|
||||||
|
jz .break_loop_divide
|
||||||
|
xor dx, dx
|
||||||
|
div bx ; dx = (dx:ax)%bx, ax = (dx:ax)/bx
|
||||||
|
push dx
|
||||||
|
inc cx ; Increase digit count
|
||||||
|
jmp .loop_divide
|
||||||
|
.break_loop_divide:
|
||||||
|
|
||||||
|
.loop_print:
|
||||||
|
pop ax
|
||||||
|
add al, '0' ; Convert to ascii
|
||||||
|
mov ah, 0xE
|
||||||
|
int 0x10
|
||||||
|
loop .loop_print
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dumpax_char:
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
mov ah, 0xE
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
keyprint:
|
||||||
|
; Enters a loop where the keycode of each pressed key is printed
|
||||||
|
; [ESC] exits the loop
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov si, .f_info
|
||||||
|
call print
|
||||||
|
|
||||||
|
.keyprint_loop:
|
||||||
|
mov ax, 0x1000 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
|
||||||
|
mov bx, ax ; Save KeyCode in bx
|
||||||
|
|
||||||
|
print_format .f, ax, ax
|
||||||
|
|
||||||
|
cmp bx, 0x011B ; ESC key
|
||||||
|
je .break_keyprint_loop
|
||||||
|
|
||||||
|
jmp .keyprint_loop
|
||||||
|
.break_keyprint_loop:
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
.f_info: db 13, 10, "Press keys to see their keycodes.",13,10,"Press [ESC] to exit.", 13, 10, 0
|
||||||
|
.f: db "(%c: %x)", 13, 10, 0
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dump_stack_registers:
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push si
|
||||||
|
print_format .format_string, sp, bp
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
.format_string: db "StackRegisters(SP:%x BP:%x)", 0
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dump_general_registers:
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push si
|
||||||
|
print_format .format_string, ax, cx, dx, bx, si, di
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
.format_string: db "GeneralRegisters(ax:%x cx:%x dx:%x bx:%x si:%x di:%x)", 0
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dump_segment_registers:
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push si
|
||||||
|
print_format .format_string, ss, cs, ds, es, fs, gs
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
.format_string: db "SegmentRegisters(Stack:%x Code:%x Data:%x Extra:%x F:%x G:%x)", 0
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
_print_format:
|
||||||
|
; IN: variable number of 16-bit numbers on stack
|
||||||
|
; IN: 'si' points to beginning of format string with the following format:
|
||||||
|
; %x in string replaced with hexadecimal representation
|
||||||
|
; %d in string replaced with decimal representation
|
||||||
|
; %% in string replaced with literal % sign
|
||||||
|
;
|
||||||
|
; EXAMPLE call:
|
||||||
|
; push word 1337
|
||||||
|
; push word 0xbeef
|
||||||
|
; push word 0xdead
|
||||||
|
; lea si, [.FORMAT]
|
||||||
|
; call print_format ; output: "(DEAD-BEEF){1337} 100%"
|
||||||
|
; add sp, 6
|
||||||
|
; (...)
|
||||||
|
; .FORMAT: db "(%x-%x){%d} 100%%",0
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
pushf
|
||||||
|
pusha
|
||||||
|
|
||||||
|
lea bp, [bp+4]
|
||||||
|
|
||||||
|
.outer_loop:
|
||||||
|
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
|
||||||
|
|
||||||
|
.print_loop:
|
||||||
|
lodsb ; al = *si++
|
||||||
|
cmp al, '%'
|
||||||
|
je .break_print
|
||||||
|
test al, al
|
||||||
|
jz .break_outer
|
||||||
|
int 0x10
|
||||||
|
jmp .print_loop
|
||||||
|
.break_print:
|
||||||
|
|
||||||
|
lodsb
|
||||||
|
cmp al, 'x'
|
||||||
|
je .format_hex
|
||||||
|
cmp al, 'd'
|
||||||
|
je .format_dec
|
||||||
|
cmp al, 'c'
|
||||||
|
je .format_char
|
||||||
|
cmp al, '%'
|
||||||
|
je .print_literal_percent
|
||||||
|
|
||||||
|
.format_hex:
|
||||||
|
lea cx, [dumpax]
|
||||||
|
jmp .print_ax
|
||||||
|
.format_dec:
|
||||||
|
lea cx, [dumpax10]
|
||||||
|
jmp .print_ax
|
||||||
|
.format_char:
|
||||||
|
lea cx, [dumpax_char]
|
||||||
|
|
||||||
|
.print_ax:
|
||||||
|
mov ax, [bp]
|
||||||
|
lea bp, [bp+2]
|
||||||
|
call cx
|
||||||
|
jmp .outer_loop
|
||||||
|
|
||||||
|
.print_literal_percent:
|
||||||
|
mov ax, (0xE<<8)|'%'
|
||||||
|
int 0x10
|
||||||
|
jmp .outer_loop
|
||||||
|
.break_outer:
|
||||||
|
|
||||||
|
popa
|
||||||
|
popf
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dump_dx_as_two_chars:
|
||||||
|
; IN dh: first char
|
||||||
|
; IN dl: second char
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
push ax
|
||||||
|
mov ah, 0xE
|
||||||
|
mov al, dh
|
||||||
|
int 0x10
|
||||||
|
mov al, dl
|
||||||
|
int 0x10
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
dump_status_flags:
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
pushf
|
||||||
|
push si
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
|
||||||
|
lahf
|
||||||
|
mov bl, ah
|
||||||
|
|
||||||
|
lea si, [.flags_string]
|
||||||
|
|
||||||
|
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
|
||||||
|
|
||||||
|
.outer_loop:
|
||||||
|
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
|
||||||
|
.print_loop:
|
||||||
|
lodsb ; Load byte at address SI into AL, and increment SI
|
||||||
|
cmp al, '%'
|
||||||
|
je .break_print_loop ; If the character is zero (NUL), stop writing the string
|
||||||
|
test al, al
|
||||||
|
jz .break_outer_loop
|
||||||
|
int 0x10 ; Otherwise, print the character via 'int 0x10'
|
||||||
|
jmp .print_loop ; Repeat for the next character
|
||||||
|
.break_print_loop:
|
||||||
|
|
||||||
|
ror bl, 1
|
||||||
|
mov al, bl
|
||||||
|
and al, 1
|
||||||
|
add al, '0'
|
||||||
|
int 0x10
|
||||||
|
jmp .outer_loop
|
||||||
|
|
||||||
|
.break_outer_loop:
|
||||||
|
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
pop si
|
||||||
|
popf
|
||||||
|
ret
|
||||||
|
.flags_string: db "Flags(Sign:% Zero:% ?:% Adjust:% ?:% Parity:% ?:% Carry:%)", 0
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
BITS 16
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
print:
|
||||||
|
; Prints string in si
|
||||||
|
; IN si: zero terminated string to print
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function
|
||||||
|
; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)]
|
||||||
|
.printchar:
|
||||||
|
lodsb ; Load byte at address SI into AL, and increment SI
|
||||||
|
test al, al
|
||||||
|
jz .done ; If the character is zero (NUL), stop writing the string
|
||||||
|
int 0x10 ; Otherwise, print the character via 'int 0x10'
|
||||||
|
jmp .printchar ; Repeat for the next character
|
||||||
|
.done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
printCRLF:
|
||||||
|
mov ah, 0xE
|
||||||
|
mov al, 13
|
||||||
|
int 0x10
|
||||||
|
mov al, 10
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
printSpace:
|
||||||
|
mov ax, 0xE20
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
printALChar:
|
||||||
|
mov ah, 0xE
|
||||||
|
mov bl, 0x02 ;color
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Changing the screen the user i looking at.
|
||||||
|
; value in 'al' is the screen we want to switch to.
|
||||||
|
; starting from 0x00
|
||||||
|
os_change_screen:
|
||||||
|
; Here the addresses for the screens stack
|
||||||
|
; and base pointer has to be set.
|
||||||
|
mov ah, 0x05
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
os_clear_screen:
|
||||||
|
pusha
|
||||||
|
; move cursor to the bootom
|
||||||
|
xor ax, ax
|
||||||
|
xor bx, bx
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x18 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
xor cx, cx
|
||||||
|
.loop:
|
||||||
|
call printCRLF
|
||||||
|
add cx, 1
|
||||||
|
cmp cx, 0x19 ; until blank screen
|
||||||
|
jne .loop
|
||||||
|
; Move curser back to the top of the screen
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x00 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
BITS 16
|
||||||
|
; THIS LIBARY IS IN REALLY BAD SHAPE
|
||||||
|
; Power_off is okay to use
|
||||||
|
|
||||||
|
power_check:
|
||||||
|
;perform an installation check
|
||||||
|
mov ah,53h ;this is an APM command
|
||||||
|
mov al,00h ;installation check command
|
||||||
|
xor bx,bx ;device id (0 = APM BIOS)
|
||||||
|
int 15h ;call the BIOS function through interrupt 15h
|
||||||
|
call printCRLF
|
||||||
|
call dumpax
|
||||||
|
;jc APM_error ;if the carry flag is set there was an error
|
||||||
|
;the function was successful
|
||||||
|
;AX = APM version number
|
||||||
|
;AH = Major revision number (in BCD format)
|
||||||
|
;AL = Minor revision number (also BCD format)
|
||||||
|
;BX = ASCII characters "P" (in BH) and "M" (in BL)
|
||||||
|
;CX = APM flags (see the official documentation for more details)
|
||||||
|
ret
|
||||||
|
|
||||||
|
power_enable:
|
||||||
|
;Enable power management for all devices
|
||||||
|
mov ah,53h ;this is an APM command
|
||||||
|
mov al,08h ;Change the state of power management...
|
||||||
|
mov bx,0001h ;...on all devices to...
|
||||||
|
mov cx,0001h ;...power management on.
|
||||||
|
int 15h ;call the BIOS function through interrupt 15h
|
||||||
|
;jc APM_error ;if the carry flag is set there was an error
|
||||||
|
ret
|
||||||
|
|
||||||
|
power_off:
|
||||||
|
;actual shutdown command
|
||||||
|
mov ah, 0x53
|
||||||
|
mov al, 0x07
|
||||||
|
mov bx, 0x1
|
||||||
|
mov cx, 0x3
|
||||||
|
int 0x15
|
||||||
|
ret
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
BITS 16
|
||||||
|
; Compares two strings
|
||||||
|
; IN si: the first (zero terminated) string
|
||||||
|
; IN di: the second (zero terminated) string
|
||||||
|
; OUT SF and ZF (same semantics as cmp)
|
||||||
|
stringcompare:
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
.loop:
|
||||||
|
mov bl, [si]
|
||||||
|
mov bh, [di]
|
||||||
|
cmp bl, bh
|
||||||
|
jne .end
|
||||||
|
test bl, bl ; bl and bh are the same, so bl = 0 => dl = 0
|
||||||
|
jz .end
|
||||||
|
inc si
|
||||||
|
inc di
|
||||||
|
jmp .loop
|
||||||
|
.end:
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
zstring_to_integer:
|
||||||
|
;IN: si Pointer to string
|
||||||
|
;OUT: ax result in binary
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
xor ax, ax
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov bx, 10
|
||||||
|
.loop:
|
||||||
|
mov cl, [si]
|
||||||
|
cmp cl, 0
|
||||||
|
je .end
|
||||||
|
sub cl,'0'
|
||||||
|
cmp cl, 9
|
||||||
|
ja .end ; next number is not a number, or its a zero, and then we are done
|
||||||
|
; multiply by 10, and add the new number.
|
||||||
|
mul bx
|
||||||
|
add ax, cx
|
||||||
|
inc si
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.end:
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
+290
@@ -0,0 +1,290 @@
|
|||||||
|
BITS 16
|
||||||
|
svim:
|
||||||
|
pusha ; save state before program
|
||||||
|
;mov si, .os_clear_screen_str
|
||||||
|
;call print
|
||||||
|
xor bx, bx
|
||||||
|
call os_clear_screen
|
||||||
|
;xor cx, cx ; Upper and left coordinate
|
||||||
|
;mov bh, 0x0a ; color for new screen 0 = black a = light green
|
||||||
|
;mov dh, 0xff ; Select all screen
|
||||||
|
;mov dl, 0xff ; Select all screen
|
||||||
|
;mov ah, 0x07 ; scrool down
|
||||||
|
;mov al, 0x00 ; scrool 0 lines (means blank screen )
|
||||||
|
;int 0x10
|
||||||
|
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x00 ; row zero
|
||||||
|
mov dl, 0x17 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
mov si, .welcome_svim_select_file
|
||||||
|
call print
|
||||||
|
call printCRLF
|
||||||
|
mov si, .seperate_line
|
||||||
|
call print
|
||||||
|
call vsfs_list_files_command
|
||||||
|
|
||||||
|
; move cursor to the bootom
|
||||||
|
xor ax, ax
|
||||||
|
xor bx, bx
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x17 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov si, .welcome_svim
|
||||||
|
call print
|
||||||
|
call printCRLF
|
||||||
|
mov si, .welcome_svim_enter_fileindex
|
||||||
|
call print
|
||||||
|
|
||||||
|
; Ask the user for the filename
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx ; are going to be the counter
|
||||||
|
xor dx, dx
|
||||||
|
.enter_fileindex_loop:
|
||||||
|
push cx
|
||||||
|
.loop_no_push:
|
||||||
|
mov ax, 0x10 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
cmp ax, 0x1c0d ; enter key
|
||||||
|
je .fileindex_done
|
||||||
|
cmp ax, 0x0e08 ; backspace
|
||||||
|
jne .no_enter_fileindex
|
||||||
|
cmp cx, 0
|
||||||
|
je .loop_no_push
|
||||||
|
pop cx
|
||||||
|
sub cx, 1
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, cx
|
||||||
|
mov BYTE [bx], 0
|
||||||
|
; Go back one space
|
||||||
|
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Place a NULL
|
||||||
|
mov al, 0x0 ; NULL
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Go back one space again as the above print of NULL pushes the cursor forward again.
|
||||||
|
mov ax, 0x0e08
|
||||||
|
int 0x10
|
||||||
|
jmp .enter_fileindex_loop
|
||||||
|
|
||||||
|
.no_enter_fileindex:
|
||||||
|
mov bh, 0x00
|
||||||
|
mov bl, 0x02
|
||||||
|
mov ah, 0x0E
|
||||||
|
int 0x10 ; print char
|
||||||
|
pop cx
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, cx
|
||||||
|
mov [bx], al
|
||||||
|
add cx, 1
|
||||||
|
; fileindex must only be 120 chars
|
||||||
|
cmp cx, 120
|
||||||
|
jae .fileindex_done
|
||||||
|
|
||||||
|
jmp .enter_fileindex_loop
|
||||||
|
|
||||||
|
.fileindex_done:
|
||||||
|
pop cx ; Cleanup, and now contain filename size
|
||||||
|
mov ax, cx
|
||||||
|
add ax, .buffer_for_svim
|
||||||
|
mov bx, ax
|
||||||
|
mov BYTE [bx], 0
|
||||||
|
mov si, .buffer_for_svim
|
||||||
|
call zstring_to_integer ; ax now contain the interger index for the file
|
||||||
|
mov [.fileindex_for_open_file], ax ; save the file index
|
||||||
|
|
||||||
|
call os_clear_screen
|
||||||
|
|
||||||
|
; move cursor to the bootom
|
||||||
|
xor ax, ax
|
||||||
|
xor bx, bx
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x17 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov si, .seperate_line
|
||||||
|
call print
|
||||||
|
mov si, .welcome_svim
|
||||||
|
call print
|
||||||
|
|
||||||
|
; move cursor to the top
|
||||||
|
xor ax, ax
|
||||||
|
xor bx, bx
|
||||||
|
mov ah, 0x02
|
||||||
|
mov bh, 0x00 ; page number 0
|
||||||
|
mov dh, 0x00 ; row zero
|
||||||
|
mov dl, 0x00 ; coloumn zero
|
||||||
|
int 0x10
|
||||||
|
; Load from disk and, enter it, into the buffer
|
||||||
|
|
||||||
|
mov si, .welcome_svim_select_file
|
||||||
|
call print
|
||||||
|
|
||||||
|
mov ax, [.fileindex_for_open_file]
|
||||||
|
|
||||||
|
call dumpax10
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
mov si, .seperate_line
|
||||||
|
call print
|
||||||
|
|
||||||
|
mov ax, [.fileindex_for_open_file]
|
||||||
|
|
||||||
|
mov ch, al ; move the fileindex in the ch
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
xor bx, bx
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
xor ax, ax
|
||||||
|
mov ah, 0x02 ;Read sectors from drive
|
||||||
|
mov al, 0x04 ;Number of sectors to read (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x00 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, 2046
|
||||||
|
mov ax, [bx]
|
||||||
|
mov [.buffer_counter_svim], ax
|
||||||
|
; print buffer
|
||||||
|
mov si, .buffer_for_svim
|
||||||
|
mov es, si
|
||||||
|
call print
|
||||||
|
|
||||||
|
.svim_loop:
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov ax, 0x1000 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
cmp ax, 0x1c0d ; enter key
|
||||||
|
jne .no_enter
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, [.buffer_counter_svim]
|
||||||
|
mov BYTE [bx], 13 ; put char in the buffer
|
||||||
|
mov BYTE [bx + 1], 10 ; put char in the buffer
|
||||||
|
mov bx, [.buffer_counter_svim]
|
||||||
|
add bx, 0x02
|
||||||
|
mov [.buffer_counter_svim], bx
|
||||||
|
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov ax, 0x0e0d
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
mov ax, 0x0e0a
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
jmp .svim_loop
|
||||||
|
|
||||||
|
.no_enter:
|
||||||
|
cmp ax, 0x11b ; ESC key
|
||||||
|
je .end_svim
|
||||||
|
;cmp ax, 0x3c00 ; f2 key
|
||||||
|
;je .f_key_pushed
|
||||||
|
cmp ax, 0x0e08 ; backspace
|
||||||
|
je .backspace_pushed
|
||||||
|
mov bx, ax
|
||||||
|
mov ax, 0xe20
|
||||||
|
mov al, bl
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, [.buffer_counter_svim]
|
||||||
|
mov [bx], al ; put char in the buffer
|
||||||
|
mov bx, [.buffer_counter_svim]
|
||||||
|
add bx, 0x01
|
||||||
|
mov [.buffer_counter_svim], bx
|
||||||
|
|
||||||
|
int 0x10 ; print char
|
||||||
|
jmp .svim_loop
|
||||||
|
.end_svim:
|
||||||
|
; save the written buffer
|
||||||
|
;AH 03h
|
||||||
|
;AL Sectors To Write Count
|
||||||
|
;CH Track
|
||||||
|
;CL Sector
|
||||||
|
;DH Head
|
||||||
|
;DL Drive
|
||||||
|
;ES:BX Buffer Address Pointer
|
||||||
|
mov ax, [.buffer_counter_svim]
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, 2046
|
||||||
|
mov [bx], ax
|
||||||
|
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
|
||||||
|
mov ax, [.fileindex_for_open_file]
|
||||||
|
mov ch, al ; move the fileindex in the ch
|
||||||
|
|
||||||
|
mov ah, 0x03 ;Write sectors to drive
|
||||||
|
mov al, 0x04 ;Number of sectors to write (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x00 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
|
||||||
|
; clean up swim
|
||||||
|
;xor bx, bx
|
||||||
|
;xor cx, cx ; Upper and left coordinate
|
||||||
|
;mov bh, 0x0f ; color for new screen 0 = black f = white
|
||||||
|
;mov dh, 0xff ; Select all screen
|
||||||
|
;mov dl, 0xff ; Select all screen
|
||||||
|
;mov ah, 0x07 ; scrool down
|
||||||
|
;mov al, 0x00 ; scrool 0 lines (means blank screen )
|
||||||
|
;int 0x10
|
||||||
|
call os_clear_screen
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.backspace_pushed:
|
||||||
|
mov bx, [.buffer_counter_svim]
|
||||||
|
cmp bx, 0
|
||||||
|
je .svim_loop
|
||||||
|
;print_format .debug_buffer_counter, bx
|
||||||
|
mov cx, bx
|
||||||
|
sub cx, 1
|
||||||
|
mov bx, .buffer_for_svim
|
||||||
|
add bx, cx
|
||||||
|
mov BYTE [bx], 0
|
||||||
|
mov [.buffer_counter_svim], cx
|
||||||
|
;print_format .debug_buffer_counter, cx
|
||||||
|
; Go back one space
|
||||||
|
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Place a NULL
|
||||||
|
mov al, 0x0 ; NULL
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Go back one space again as the above print of NULL pushes the cursor forward again.
|
||||||
|
mov ax, 0x0e08
|
||||||
|
int 0x10
|
||||||
|
jmp .svim_loop
|
||||||
|
|
||||||
|
|
||||||
|
;.f_key_pushed:
|
||||||
|
;mov al, 0x01 ;arg: index 1
|
||||||
|
;call os_change_screen
|
||||||
|
;jmp .svim_loop
|
||||||
|
|
||||||
|
;.load_buffer_svim:
|
||||||
|
|
||||||
|
.debug_buffer_counter db 'Buffer count: %d', 13, 10, 0
|
||||||
|
.welcome_svim db 'Vim like text editor for SingOS, ESC to exit', 0
|
||||||
|
.welcome_svim_select_file db 'svim - Open file: ', 0
|
||||||
|
.welcome_svim_enter_fileindex db 'Enter fileindex: ', 0
|
||||||
|
.seperate_line db '________________________________________________________________________________', 0
|
||||||
|
.fileindex_for_open_file dw 0
|
||||||
|
.buffer_for_svim times 2048 db 0 ; db 'this is the buffer', 0, times 32 db 0
|
||||||
|
.buffer_counter_svim dw 0
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
BITS 16
|
||||||
|
|
||||||
|
mem_get_zstack_buffer:
|
||||||
|
; INPUT size of zeroed buffer ax in bytes
|
||||||
+342
@@ -0,0 +1,342 @@
|
|||||||
|
BITS 16
|
||||||
|
vsfs_format_disk:
|
||||||
|
; When SingOS it booted for the first time,
|
||||||
|
; we have to format the disk to create the global structure
|
||||||
|
; of the VSFS.
|
||||||
|
pusha
|
||||||
|
;AH 03h
|
||||||
|
;AL Sectors To Write Count
|
||||||
|
;CH Track
|
||||||
|
;CL Sector
|
||||||
|
;DH Head
|
||||||
|
;DL Drive
|
||||||
|
|
||||||
|
; Set the es to point to the data segment,
|
||||||
|
; this is the global segment, where we calculate all
|
||||||
|
; our adresses from
|
||||||
|
; ES:BX Buffer Address Pointer
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
|
||||||
|
; Set the bx to point to the pointer of the sector we have to write
|
||||||
|
; to the disk.
|
||||||
|
mov bx, .vsfs_format_disk_buffer
|
||||||
|
mov ah, 0x03 ;Write sectors to drive
|
||||||
|
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov ch, 0x08
|
||||||
|
mov dh, 0x00 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.vsfs_format_disk_buffer db 'VSFS v0.1', 13, 10, '(VerySimpelFileSystem)', 13, 10, 'Developed to SingOS', 13, 10, 'by Jorn Guldberg', 13, 10, 0 ; 66 chars + 8 bytes
|
||||||
|
times 431 db 0
|
||||||
|
dw 8, 0, 9 ; Start index, number of files, next free index
|
||||||
|
|
||||||
|
vsfs_get_fs_info:
|
||||||
|
pusha
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
mov bx, vsfs_loading_buffer
|
||||||
|
|
||||||
|
mov ah, 0x02 ; Read sectors from drive
|
||||||
|
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes)
|
||||||
|
mov ch, 0x08 ; cylinder
|
||||||
|
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x00 ; Head number
|
||||||
|
mov dl, [global_disk_identifier] ; Drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov si, vsfs_loading_buffer
|
||||||
|
call print
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
vsfs_read_file_index_in_ax:
|
||||||
|
; INPUT ax = file index
|
||||||
|
; INPUT bx = filebuffer
|
||||||
|
pusha ; save all register state
|
||||||
|
;call vsfs_convert_index_into_regs
|
||||||
|
;mov bx, .buffer_for_svim
|
||||||
|
push bx
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
mov ch, al ; Low 8 bits of cylinder
|
||||||
|
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits
|
||||||
|
mov ah, 0x02 ; Read sectors from drive
|
||||||
|
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x00 ; Head number
|
||||||
|
mov dl, [global_disk_identifier] ; Drive number
|
||||||
|
int 0x13
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
vsfs_write_file_to_index_in_ax:
|
||||||
|
pusha ; save all register state
|
||||||
|
;AH 03h
|
||||||
|
;AL Sectors To Write Count
|
||||||
|
;CH Track
|
||||||
|
;CL Sector
|
||||||
|
;DH Head
|
||||||
|
;DL Drive
|
||||||
|
;ES:BX Buffer Address Pointer
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
xor bx, bx
|
||||||
|
;mov bx, .buffer_for_svim
|
||||||
|
xor cx, cx
|
||||||
|
xor ax, ax
|
||||||
|
mov ah, 0x03 ;Write sectors to drive
|
||||||
|
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x03 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov ch, 0x02
|
||||||
|
mov dh, 0x01 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
vsfs_convert_index_into_regs:
|
||||||
|
; This function takes a file index in ax, do the calculations
|
||||||
|
; to set the registers to the right place at the disk
|
||||||
|
; CH Track
|
||||||
|
; CL Sector
|
||||||
|
; DH Head
|
||||||
|
; The rest of the parameters is set in the read and write function.
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
vsfs_create_file:
|
||||||
|
; ax pointer to filename
|
||||||
|
; bx size
|
||||||
|
; cx fileIndex
|
||||||
|
|
||||||
|
pusha ; save all register state
|
||||||
|
|
||||||
|
mov si, .vsfs_create_file_type_filename
|
||||||
|
call print
|
||||||
|
|
||||||
|
; Ask the user for the filename
|
||||||
|
xor bx, bx
|
||||||
|
xor cx, cx ; are going to be the counter
|
||||||
|
xor dx, dx
|
||||||
|
.enter_filename_loop:
|
||||||
|
push cx
|
||||||
|
mov ax, 0x10 ; BIOS call to wait for key
|
||||||
|
int 0x16
|
||||||
|
cmp ax, 0x1c0d ; enter key
|
||||||
|
je .filename_done
|
||||||
|
|
||||||
|
cmp ax, 0x0e08 ; backspace
|
||||||
|
jne .no_enter
|
||||||
|
pop cx
|
||||||
|
cmp cx, 0
|
||||||
|
je .enter_filename_loop
|
||||||
|
|
||||||
|
sub cx, 1
|
||||||
|
mov bx, .new_filename_buffer
|
||||||
|
add bx, cx
|
||||||
|
mov BYTE [bx], 0
|
||||||
|
; Go back one space
|
||||||
|
mov ax, 0x0e08 ; ah=0x0e means teletype output. al=0x08 means backspace character.
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Place a NULL
|
||||||
|
mov al, 0x0 ; NULL
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
; Go back one space again as the above print of NULL pushes the cursor forward again.
|
||||||
|
mov ax, 0x0e08
|
||||||
|
int 0x10
|
||||||
|
jmp .enter_filename_loop
|
||||||
|
|
||||||
|
.no_enter:
|
||||||
|
mov bh, 0x00
|
||||||
|
mov bl, 0x02
|
||||||
|
mov ah, 0x0E
|
||||||
|
int 0x10 ; print char
|
||||||
|
pop cx
|
||||||
|
mov bx, .new_filename_buffer
|
||||||
|
add bx, cx
|
||||||
|
mov [bx], al
|
||||||
|
add cx, 1
|
||||||
|
; filename must only be 120 chars
|
||||||
|
cmp cx, 120
|
||||||
|
jae .filename_done
|
||||||
|
|
||||||
|
jmp .enter_filename_loop
|
||||||
|
|
||||||
|
.filename_done:
|
||||||
|
pop cx ; Cleanup, and now contain filename size
|
||||||
|
mov bx, .new_filename_buffer
|
||||||
|
add bx, cx
|
||||||
|
mov BYTE [bx], 0
|
||||||
|
call printCRLF
|
||||||
|
|
||||||
|
|
||||||
|
; We first need to know the index for the file.
|
||||||
|
; The next avaliable index are we going to get from the
|
||||||
|
; FSinfo sctor of the disk:
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
|
||||||
|
mov bx, vsfs_loading_buffer
|
||||||
|
mov ch, 0x08 ; Low 8 bits of cylinder
|
||||||
|
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits
|
||||||
|
mov ah, 0x02 ; Read sectors from drive
|
||||||
|
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov dh, 0x00 ; Head number
|
||||||
|
mov dl, [global_disk_identifier] ; Drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov ax, [vsfs_loading_buffer + 510]
|
||||||
|
mov [.to_write_fileindex], ax
|
||||||
|
|
||||||
|
; We have to do modulo 4, to know where in the sector the
|
||||||
|
; file entry has to be written
|
||||||
|
add DWORD [vsfs_loading_buffer + 510], 1
|
||||||
|
add DWORD [vsfs_loading_buffer + 508], 1
|
||||||
|
|
||||||
|
mov bx, vsfs_loading_buffer
|
||||||
|
mov ah, 0x03 ;Write sectors to drive
|
||||||
|
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes)
|
||||||
|
mov cl, 0x01 ;First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov ch, 0x08
|
||||||
|
mov dh, 0x00 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
|
||||||
|
; Now we have the index in ax.
|
||||||
|
|
||||||
|
;AH 03h
|
||||||
|
;AL Sectors To Write Count
|
||||||
|
;CH Track
|
||||||
|
;CL Sector
|
||||||
|
;DH Head
|
||||||
|
;DL Drive
|
||||||
|
|
||||||
|
; Set the es to point to the data segment,
|
||||||
|
; this is the global segment, where we calculate all
|
||||||
|
; our adresses from
|
||||||
|
; ES:BX Buffer Address Pointer
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
|
||||||
|
mov bx, [.to_write_fileindex]
|
||||||
|
sub bx, 0x07 ; Det skal den bare
|
||||||
|
mov cl, bl ; First sector to write (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
; Set the bx to point to the pointer of the sector we have to write
|
||||||
|
; to the disk.
|
||||||
|
mov bx, .new_filename_buffer
|
||||||
|
mov ah, 0x03 ;Write sectors to drive
|
||||||
|
mov al, 0x01 ;Number of sectors to write (8 * 512 = 4096 bytes)
|
||||||
|
mov ch, 0x08
|
||||||
|
mov dh, 0x00 ;Head number
|
||||||
|
mov dl, [global_disk_identifier] ;Drive number
|
||||||
|
int 0x13 ;Low level disk services
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.vsfs_create_file_type_filename db 'Enter filename: ', 0
|
||||||
|
.new_filename_buffer times 122 db 0
|
||||||
|
.new_file_size dw 0, 0
|
||||||
|
.to_write_fileindex dw 0
|
||||||
|
|
||||||
|
vsfs_list_files_command:
|
||||||
|
; This function takes the adress of the first sector of the disk
|
||||||
|
; which the OS has to know
|
||||||
|
; the adress is given by ax
|
||||||
|
|
||||||
|
; Check which registers to save
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; Load the master table into memory
|
||||||
|
;mov ax, 8 ; file index for master record
|
||||||
|
;mov bx, vsfs_loading_buffer ; pointer to the input buffer
|
||||||
|
;call vsfs_read_file_index_in_ax ; call the fucntion which read the master record
|
||||||
|
; TODO we might want this to be in memory at all times
|
||||||
|
; loaded already from boot
|
||||||
|
|
||||||
|
mov bx, ds
|
||||||
|
mov es, bx
|
||||||
|
|
||||||
|
mov si, .ls_header
|
||||||
|
call print
|
||||||
|
|
||||||
|
mov si, .seperate_line
|
||||||
|
call print
|
||||||
|
|
||||||
|
mov BYTE [.ls_counter], 1
|
||||||
|
.load_next_fileinfo:
|
||||||
|
add BYTE [.ls_counter], 1
|
||||||
|
mov bl, [.ls_counter]
|
||||||
|
mov cl, bl ; First sector to read (bits 0-5), upper bits of cylinder (bits 6-7)
|
||||||
|
mov bx, vsfs_loading_buffer
|
||||||
|
;mov ch, al ; Low 8 bits of cylinder
|
||||||
|
; the file index into ch, we need to calculatet this, if the number is larger than 16-bits
|
||||||
|
mov ah, 0x02 ; Read sectors from drive
|
||||||
|
mov al, 0x01 ; Number of sectors to read (8 * 512 = 4096 bytes)
|
||||||
|
mov ch, 0x08 ; cylinder
|
||||||
|
mov dh, 0x00 ; Head number
|
||||||
|
mov dl, [global_disk_identifier] ; Drive number
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov ax, [vsfs_loading_buffer + 126]
|
||||||
|
mov bx, ax
|
||||||
|
mov cx, ' '
|
||||||
|
mov dx, 'X'
|
||||||
|
|
||||||
|
cmp ax, 0
|
||||||
|
je .end_ls
|
||||||
|
cmp ax, 10
|
||||||
|
ja .index_over_10
|
||||||
|
mov [.fileentry_line + 3 ], cx
|
||||||
|
mov [.fileentry_line + 4 ], cx
|
||||||
|
add bx, 48 ; get ascii value
|
||||||
|
mov [.fileentry_line + 5 ], bl
|
||||||
|
jmp .stop_index
|
||||||
|
.index_over_10:
|
||||||
|
cmp ax, 10
|
||||||
|
ja .index_over_100
|
||||||
|
mov [.fileentry_line + 3 ], cx
|
||||||
|
mov [.fileentry_line + 4 ], dx
|
||||||
|
mov [.fileentry_line + 5 ], dx
|
||||||
|
jmp .stop_index
|
||||||
|
|
||||||
|
.index_over_100:
|
||||||
|
mov [.fileentry_line + 3 ], dx
|
||||||
|
mov [.fileentry_line + 4 ], dx
|
||||||
|
mov [.fileentry_line + 5 ], dx
|
||||||
|
|
||||||
|
|
||||||
|
.stop_index:
|
||||||
|
|
||||||
|
mov si, .fileentry_line ; printing the buffer
|
||||||
|
call print
|
||||||
|
mov si, vsfs_loading_buffer ; printing the buffer
|
||||||
|
call print
|
||||||
|
|
||||||
|
call printCRLF
|
||||||
|
mov si, .seperate_line
|
||||||
|
|
||||||
|
call print
|
||||||
|
jmp .load_next_fileinfo
|
||||||
|
|
||||||
|
.end_ls:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
.ls_counter db 0
|
||||||
|
.ls_header db 'List of files:', 13, 10, 'Index | Filename ', 13, 10, 0
|
||||||
|
.seperate_line db '- - - - - - - - - - - - - - - - ', 13, 10, 0
|
||||||
|
.fileentry_line db ' 456 | ', 0
|
||||||
|
|
||||||
|
vsfs_loading_buffer times 512 db 0
|
||||||
Reference in new issue
Block a user