Browse Source

First commit

master
Jørn Guldberg 4 years ago
commit
62e1d36c38
23 changed files with 2501 additions and 0 deletions
  1. +5
    -0
      .gitignore
  2. +173
    -0
      CLI/CLI.nasm
  3. +39
    -0
      README.md
  4. +235
    -0
      bootloader.nasm
  5. +17
    -0
      build
  6. +16
    -0
      build.sh
  7. +305
    -0
      kernel.nasm
  8. +1
    -0
      legacy/README.md
  9. +2
    -0
      legacy/compile_folder/README.md
  10. +3
    -0
      legacy/source/build.sh
  11. +3
    -0
      legacy/source/generic_build.sh
  12. +3
    -0
      legacy/source/info.txt
  13. +76
    -0
      legacy/source/mytest.s
  14. +227
    -0
      legacy/source/mytest2.s
  15. +120
    -0
      legacy/source/sing_boot_alt.s
  16. +135
    -0
      legacy/source/sing_boot_guess.s
  17. +337
    -0
      lib/debug_tools.nasm
  18. +72
    -0
      lib/os_lib.nasm
  19. +39
    -0
      lib/std_power.nasm
  20. +57
    -0
      lib/string.nasm
  21. +290
    -0
      lib/svim.nasm
  22. +4
    -0
      mem_lib/mem_lib.nasm
  23. +342
    -0
      vsfs/vsfs.nasm

+ 5
- 0
.gitignore View File

@ -0,0 +1,5 @@
.DS_Store
*.swp
*.sublime*
*.img
*.bin

+ 173
- 0
CLI/CLI.nasm View File

@ -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

+ 39
- 0
README.md View File

@ -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
bootloader.nasm View File

@ -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

+ 17
- 0
build View File

@ -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"

+ 16
- 0
build.sh View File

@ -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
kernel.nasm View File

@ -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.

+ 1
- 0
legacy/README.md View File

@ -0,0 +1 @@
SingOs

+ 2
- 0
legacy/compile_folder/README.md View File

@ -0,0 +1,2 @@
Folder of compiling the OS
This folder has to be empty on the repository

+ 3
- 0
legacy/source/build.sh View File

@ -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

+ 3
- 0
legacy/source/generic_build.sh View File

@ -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

+ 3
- 0
legacy/source/info.txt View File

@ -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

+ 76
- 0
legacy/source/mytest.s View File

@ -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

+ 227
- 0
legacy/source/mytest2.s View File

@ -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

+ 120
- 0
legacy/source/sing_boot_alt.s View File

@ -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

+ 135
- 0
legacy/source/sing_boot_guess.s View File

@ -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

+ 337
- 0
lib/debug_tools.nasm View File

@ -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

+ 72
- 0
lib/os_lib.nasm View File

@ -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

+ 39
- 0
lib/std_power.nasm View File

@ -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

+ 57
- 0
lib/string.nasm View File

@ -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
lib/svim.nasm View File

@ -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

+ 4
- 0
mem_lib/mem_lib.nasm View File

@ -0,0 +1,4 @@
BITS 16
mem_get_zstack_buffer:
; INPUT size of zeroed buffer ax in bytes

+ 342
- 0
vsfs/vsfs.nasm View File

@ -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…
Cancel
Save