commit
62e1d36c38
23 changed files with 2501 additions and 0 deletions
@ -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 |
||||
``` |
@ -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" |
||||
|
@ -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,2 @@
|
||||
Folder of compiling the OS |
||||
This folder has to be empty on the repository |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
Loading…
Reference in new issue