Compare commits

3 Commits
master ... ed

16 changed files with 473 additions and 113 deletions

View File

@@ -15,7 +15,7 @@ $(BUILD_DIR)/crawos.iso: floppy_image
# Floppy image # Floppy image
# Fat12 # Fat12
floppy_image: $(BUILD_DIR)/crawos.img floppy_image: $(BUILD_DIR)/crawos.img
$(BUILD_DIR)/crawos.img: bootloader kernel $(BUILD_DIR)/crawos.img: bootloader kernel check-fat83
mkdir -p disk_images mkdir -p disk_images
dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image
mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12 mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12
@@ -36,6 +36,11 @@ $(BUILD_DIR)/kernel.bin:
mkdir -p disk_images mkdir -p disk_images
$(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin $(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin
check-fat83:
@echo "Checking filenames for FAT 8.3 compliance..."
@find ./data -type f | awk -F/ '{print $$NF}' | \
awk -F. 'length($$1)>8 || length($$2)>3 || NF>2 {print "Invalid FAT 8.3 filename:", $$0; bad=1} END{exit bad}'
# Clean # Clean
clean: clean:
rm -f disk_images/* rm -f disk_images/*

View File

@@ -1,9 +1,14 @@
Kernel written in Assmebly # What is this?
I'm using a modified JazzOS Bootloader This is a simple implementation of a computer kernel
written in pure x86 assembly with features including
- Read/Write disk operations
- The ability to boot from the BIOS using the JazzOS Bootloader
- A modified MikeOS BASIC interpreter
- A functional POSIX inspired CLI
Commands: # Commands
CAT - CAT <filename>: outputs the contents of the file.
HELP - LS: outputs a list of files on the system .
CLEAR - CLEAR: clears the screen.
REBOOT - REBOOT: or esc reboots the system
PONG - BAS <filename>: runs a basic script.

View File

@@ -1,2 +1,5 @@
PORT OUT 80 5 PRINT "Hello, what is your name?"
INPUT $1
PRINT "Hello " ;
PRINT $1
END END

2
data/test.asm Normal file
View File

@@ -0,0 +1,2 @@
X = 100
PRINT X

View File

@@ -1 +0,0 @@
x = 5

View File

@@ -26,7 +26,7 @@ ebr_system_id: db 'FAT12 ' ; must be 8 bytes
fat12_file_name: db ' ' ; 11 free bytes to store a filename in fat12_file_name: db ' ' ; 11 free bytes to store a filename in
boot_message: db 'OK] Kernel successfully loaded!\n"HELP" to see a list of available commands\n', 0 boot_message: db 'OK] Kernel successfully loaded!\n"HELP" to see a list of available commands\n', 0
user_input: times 20 db 0 user_input: times 20 db 0
prompt_length: db 20 prompt_length: dw 20
prompt: db 'sh > ', 0 prompt: db 'sh > ', 0
help_string: db 'HELP', 0 help_string: db 'HELP', 0
clear_string: db 'CLEAR', 0 clear_string: db 'CLEAR', 0
@@ -34,7 +34,8 @@ reboot_string: db 'REBOOT', 0
basic_string: db 'BAS', 0 basic_string: db 'BAS', 0
cat_string: db 'CAT', 0 cat_string: db 'CAT', 0
ls_string: db 'LS', 0 ls_string: db 'LS', 0
help_text: db 'This is for Cowards:\n"LS" to list the directory,\n"CAT" to output the contents of a file,\n"BAS" to run a basic script,\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 0 ed_string: db 'ED', 0
help_text: db 'This is for Cowards:\n"LS" to list the directory,\n"CAT <filename>" to output the contents of a file,\n"BAS <filename>" to run a basic script,\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 0
basic_text: db 'BASIC PROGRAM BEGUN:\n', 0 basic_text: db 'BASIC PROGRAM BEGUN:\n', 0
command_result_text: db 'You typed: ', 0 command_result_text: db 'You typed: ', 0
unknown_command: db 'Error: Unkown Command..\n ', 0 unknown_command: db 'Error: Unkown Command..\n ', 0
@@ -47,12 +48,6 @@ file_not_found: db 'File not found\n', 0
too_long_filename: db 'Filename too long for Fat12\n', 0 too_long_filename: db 'Filename too long for Fat12\n', 0
file_found: db 'File found\n', 0 file_found: db 'File found\n', 0
loading_root: db 'Loading root diretory\n', 0 loading_root: db 'Loading root diretory\n', 0
read_only: db 'Read Only', 0 ; 1
hidden: db ' Hidden ', 0 ; 2
system: db ' System ', 0 ; 4
volume: db ' Volume ', 0 ; 8
directory: db 'Directory', 0 ; 10
archive: db ' Archive ', 0 ; 20
file_name_length: db 0 file_name_length: db 0
file_cluster: dw 0 file_cluster: dw 0
file_length: dd 0 file_length: dd 0

View File

@@ -842,14 +842,14 @@ do_break:
do_call: do_call:
call get_token call get_token
cmp ax, NUMBER cmp ax, NUMBER
je .is_number je .check_is_number
mov ax, 0 mov ax, 0
mov byte al, [token] mov byte al, [token]
call get_var call get_var
jmp .execute_call jmp .execute_call
.is_number: .check_is_number:
mov si, token mov si, token
call string_cast_to_int call string_cast_to_int
@@ -1325,7 +1325,7 @@ do_for:
cmp ax, NUMBER cmp ax, NUMBER
jne .error jne .error
.second_is_number: .second_check_is_number:
mov si, token ; Get target number mov si, token ; Get target number
call string_cast_to_int call string_cast_to_int
jmp .continue2 jmp .continue2
@@ -1625,7 +1625,7 @@ do_if:
je .equals_char je .equals_char
mov byte al, [token] mov byte al, [token]
call is_letter call check_is_letter
jc .equals_var jc .equals_var
mov si, token ; Otherwise it's, eg 'X = 1' (a number) mov si, token ; Otherwise it's, eg 'X = 1' (a number)
@@ -1711,7 +1711,7 @@ do_if:
.greater: .greater:
call get_token ; Greater than a variable or number? call get_token ; Greater than a variable or number?
mov byte al, [token] mov byte al, [token]
call is_letter call check_is_letter
jc .greater_var jc .greater_var
mov si, token ; Must be a number here... mov si, token ; Must be a number here...
@@ -1736,7 +1736,7 @@ do_if:
.less: .less:
call get_token call get_token
mov byte al, [token] mov byte al, [token]
call is_letter call check_is_letter
jc .less_var jc .less_var
mov si, token mov si, token
@@ -1950,8 +1950,9 @@ do_input:
.number_var: .number_var:
mov ax, .tmpstring ; Get input from the user mov ax, .tmpstring ; Get input from the user
mov bx, 6 mov bx, 20
call keyboard_display_input call keyboard_display_input
jc .end
mov ax, .tmpstring mov ax, .tmpstring
call string_length call string_length
@@ -1973,8 +1974,6 @@ do_input:
call os_print_newline call os_print_newline
jmp mainloop jmp mainloop
.string_var: .string_var:
mov ax, 128 mov ax, 128
mul bx mul bx
@@ -1987,8 +1986,9 @@ do_input:
jmp mainloop jmp mainloop
.tmpstring times 20 db 0
.tmpstring times 6 db 0 .end
ret
; ----------------------------------------------------------- ; -----------------------------------------------------------
@@ -2636,7 +2636,7 @@ do_peekint:
cmp ax, NUMBER cmp ax, NUMBER
jne .error jne .error
.address_is_number: .address_check_is_number:
mov si, token mov si, token
call string_cast_to_int call string_cast_to_int
jmp .load_data jmp .load_data
@@ -3770,14 +3770,14 @@ do_string:
call get_token ; Now there should be a number call get_token ; Now there should be a number
cmp ax, NUMBER cmp ax, NUMBER
je .third_is_number je .third_check_is_number
cmp ax, VARIABLE cmp ax, VARIABLE
je .third_is_variable je .third_is_variable
jmp .error jmp .error
.third_is_number: .third_check_is_number:
mov si, token mov si, token
call string_cast_to_int call string_cast_to_int
jmp .got_number jmp .got_number
@@ -3984,7 +3984,7 @@ get_token:
cmp al, ' ' cmp al, ' '
je .newline je .newline
call is_number call check_is_number
jc get_number_token jc get_number_token
cmp al, '"' cmp al, '"'
@@ -4030,7 +4030,7 @@ get_number_token:
je .done je .done
cmp al, ' ' cmp al, ' '
je .done je .done
call is_number call check_is_number
jc .fine jc .fine
mov si, err_char_in_num mov si, err_char_in_num
@@ -4153,7 +4153,7 @@ get_string_token:
.is_not_string: .is_not_string:
mov byte al, [token] mov byte al, [token]
call is_letter call check_is_letter
jc .is_var jc .is_var
mov ax, UNKNOWN mov ax, UNKNOWN
@@ -4164,37 +4164,6 @@ get_string_token:
ret ret
; ------------------------------------------------------------------
; Set carry flag if AL contains ASCII number
is_number:
cmp al, 48
jl .not_number
cmp al, 57
jg .not_number
stc
ret
.not_number:
clc
ret
; ------------------------------------------------------------------
; Set carry flag if AL contains ASCII letter
is_letter:
cmp al, 65
jl .not_letter
cmp al, 90
jg .not_letter
stc
ret
.not_letter:
clc
ret
; ------------------------------------------------------------------ ; ------------------------------------------------------------------
; Print error message and quit out ; Print error message and quit out

View File

@@ -0,0 +1,29 @@
check_is_number:
cmp al, 48
jl .not_number
cmp al, 57
jg .not_number
stc
ret
.not_number:
clc
ret
check_is_letter:
cmp al, 65
jl .not_letter
cmp al, 122
jg .not_letter
cmp al, 90
jg .maybe_not_letter
stc
ret
.maybe_not_letter:
cmp al, 97
jl .not_letter
stc
ret
.not_letter:
clc
ret

View File

@@ -1,5 +1,6 @@
os_start_cli: os_start_cli:
pusha pusha
call os_print_newline call os_print_newline
@@ -11,6 +12,7 @@ os_start_cli:
mov ax, user_input mov ax, user_input
call keyboard_display_input call keyboard_display_input
jc power_reboot
jmp os_read_cli jmp os_read_cli
@@ -30,14 +32,14 @@ os_read_cli:
mov di, help_string mov di, help_string
call os_compare_strings call os_compare_strings
cmp cl, 1 cmp cl, 1
je help je .help
; Clear screen ; Clear screen
mov si, user_input mov si, user_input
mov di, clear_string mov di, clear_string
call os_compare_strings call os_compare_strings
cmp cl, 1 cmp cl, 1
je clear je .clear
; Reboot ; Reboot
mov si, user_input mov si, user_input
@@ -51,22 +53,29 @@ os_read_cli:
mov di, basic_string mov di, basic_string
call os_compare_strings call os_compare_strings
cmp cl, 1 cmp cl, 1
je basic je .basic
; Cat ; Cat
mov si, user_input mov si, user_input
mov di, cat_string mov di, cat_string
call os_compare_strings call os_compare_strings
cmp cl, 1 cmp cl, 1
je cat je .cat
; LS ; LS
mov si, user_input mov si, user_input
mov di, ls_string mov di, ls_string
call os_compare_strings call os_compare_strings
cmp cl, 1 cmp cl, 1
je ls je .ls
;ED
mov si, user_input
mov di, ed_string
call os_compare_strings
cmp cl, 1
je .ed
jmp .unkown jmp .unkown
.unkown: .unkown:
@@ -77,24 +86,33 @@ os_read_cli:
jmp .finish jmp .finish
.finish: .finish:
; Clear the user input
mov al, 0
mov cx, 20
mov di,user_input
repe stosb
popa popa
call os_start_cli call os_start_cli
clear: .clear:
call os_set_text_mode call os_set_text_mode
call os_read_cli.finish call os_read_cli.finish
help: .help:
mov si, help_text mov si, help_text
call os_print_string call os_print_string
call os_read_cli.finish call os_read_cli.finish
basic: .basic:
call util_basic call util_basic
call os_read_cli.finish call os_read_cli.finish
cat: .cat:
call util_cat call util_cat
call os_read_cli.finish call os_read_cli.finish
ls: .ls:
call util_ls call util_ls
call os_read_cli.finish call os_read_cli.finish
.ed:
call util_ed
call os_read_cli.finish

View File

@@ -171,6 +171,7 @@ disk_clear_output_buffer:
; OUT ; OUT
; data_buffer: file contents ; data_buffer: file contents
; TODO use predefined data for calculations ; TODO use predefined data for calculations
; CX = 0 if failed to load
disk_load_file: disk_load_file:
pusha pusha
call string_length ; cl = string length call string_length ; cl = string length
@@ -227,13 +228,18 @@ disk_load_file:
.file_not_found: .file_not_found:
mov si, file_not_found mov si, file_not_found
call os_print_string call os_print_string
jmp .done jmp .done_fail
.filename_too_long: .filename_too_long:
mov si, too_long_filename mov si, too_long_filename
call os_print_string call os_print_string
jmp .done jmp .done_fail
.done_fail:
popa
mov bx, 1
ret
.done: .done:
popa popa
xor bx,bx
ret ret
; Write data to file ; Write data to file

View File

@@ -15,6 +15,7 @@ os_read_input:
; AX = key pressed ; AX = key pressed
; Returns straight away ; Returns straight away
; carry flag is set when escape is pressed and data is returned straight away
keyboard_check_key: keyboard_check_key:
xor ax,ax xor ax,ax
mov ah, 11h ; BIOS call to check for key mov ah, 11h ; BIOS call to check for key
@@ -27,12 +28,13 @@ keyboard_check_key:
; IN: ; IN:
; AX = output address ; AX = output address
; BX = max length ; BX = max length
; OUT:
; BX = 1 if escape is pressed
keyboard_display_input: keyboard_display_input:
pusha pusha
mov di, ax mov di, ax
mov ax, bx xor ax,ax
mov bx,20 mov [prompt_length], bx
.check_key_pressed: .check_key_pressed:
call os_read_input call os_read_input
@@ -55,16 +57,19 @@ keyboard_display_input:
jmp .check_key_pressed jmp .check_key_pressed
.esc_key: .esc_key:
call power_reboot popa
mov bx, 1
ret
.enter_key: .enter_key:
mov al, 0 mov al, 0
stosb stosb
popa popa
xor bx,bx
ret ; Return to the parent function (whatever that may be) ret ; Return to the parent function (whatever that may be)
.backspace: .backspace:
cmp bx, 20 ; Cannot backspace if the cursor is at the start cmp bx, [prompt_length] ; Cannot backspace if the cursor is at the start
jb .move_cursor_back ; then .move_cursor_back jb .move_cursor_back ; then .move_cursor_back
jmp .check_key_pressed ; Else check the next key jmp .check_key_pressed ; Else check the next key
@@ -87,6 +92,7 @@ keyboard_display_input:
mov ah, 0Eh mov ah, 0Eh
int 10h int 10h
jmp .check_key_pressed jmp .check_key_pressed
.input_length db 0
keyboard_get_cursor_pos: keyboard_get_cursor_pos:
ret ret

View File

@@ -106,35 +106,42 @@ string_join:
ret ret
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; TODO ; Converts a string to an integer
; Converts a null terminated string to an integer
; IN: SI = string location (max 5 chars, up to '65536') ; IN: SI = string location (max 5 chars, up to '65536')
; OUT: AX = number ; OUT: AX = number, DX = length of int string
string_cast_to_int: string_cast_to_int:
pusha push cx
push bx
push dx
xor cx,cx xor cx,cx
.loop: .loop:
xor ax,ax xor ax,ax
lodsb lodsb
cmp al, 0
je .finish ; Exit if the character is not a number
sub al, 30h cmp al,'0'
jl .finish
cmp al,'9'
jg .finish
sub al, '0'
mov bx, ax mov bx, ax
mov ax, 10 mov ax, 10
mul cx ; Multiple the current value by 10 mul cx ; Multiple the current value by 10
add ax, bx ; Then add the new digit add ax, bx ; Then add the new digit
mov cx, ax mov cx, ax
jmp .loop jmp .loop
.finish: .finish:
mov [int_tmp], cx mov ax,cx
popa pop dx
mov ax, [int_tmp] pop bx
pop cx
ret ret
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; IN: AX = integer (unsigned) ; IN: AX = integer (unsigned)
; OUT: AX -> null-terminated string ; OUT: AX -> null-terminated string
string_cast_from_int: string_cast_from_int:
pusha pusha
cld ; Write backwards cld ; Write backwards

View File

@@ -55,10 +55,16 @@ text_print_raw:
je .space je .space
cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL
je .new_line je .new_line
cmp al, 09h ; TAB
je .tab
cmp al, 0Dh cmp al, 0Dh
je .repeat je .repeat
int 10h int 10h
jmp .repeat jmp .repeat
.tab:
mov al, ' '
int 10h
jmp .repeat
.space: .space:
mov al, 20h mov al, 20h
int 10h int 10h
@@ -129,6 +135,15 @@ os_set_text_mode:
mov dh, 0 mov dh, 0
mov dl, 0 mov dl, 0
int 10h int 10h
text_newline:
pusha
mov ax,0E0Ah
int 10h
mov al,0Dh
int 10h
popa
ret
popa popa
ret ret

View File

@@ -1,30 +1,33 @@
util_cat: util_cat:
pusha pusha
call disk_clear_file_buffer call disk_clear_file_buffer
mov si, user_input mov si, user_input
; TODO make this more consistent to account for double spaces ; TODO make this more consistent to account for double spaces
add si, 4 ; Move si to after 'CAT' add si, 4 ; Move si to after 'CAT'
call disk_load_file call disk_load_file
mov si, file_buffer cmp bx, 1
mov cx, [file_length] je .done
call text_print_raw
popa mov si, file_buffer
ret mov cx, [file_length]
call text_print_raw
.done
popa
ret
util_ls: util_ls:
pusha pusha
call disk_list_contents call disk_list_contents
mov si, output_buffer mov si, output_buffer
call os_print_string call os_print_string
call disk_clear_output_buffer call disk_clear_output_buffer
popa popa
ret ret
util_basic: util_basic:
pusha pusha
@@ -34,6 +37,8 @@ util_basic:
; TODO make this more consistent to account for double spaces ; TODO make this more consistent to account for double spaces
;add si, 3 ; Move si to after 'BAS' ;add si, 3 ; Move si to after 'BAS'
call disk_load_file call disk_load_file
cmp bx, 1
je .done
mov si, file_buffer mov si, file_buffer
@@ -41,5 +46,16 @@ util_basic:
mov si, 0 mov si, 0
call basic_run_basic call basic_run_basic
.done
popa
ret
util_ed:
pusha
call disk_load_root
call disk_load_file
call ed
popa popa
ret ret

View File

@@ -33,13 +33,19 @@ halt:
%INCLUDE "source/kernel/features/sound.asm" %INCLUDE "source/kernel/features/sound.asm"
%INCLUDE "source/kernel/features/disk.asm" %INCLUDE "source/kernel/features/disk.asm"
%INCLUDE "source/kernel/features/math.asm" %INCLUDE "source/kernel/features/math.asm"
%INCLUDE "source/kernel/features/check.asm"
%INCLUDE "source/kernel/features/time.asm" %INCLUDE "source/kernel/features/time.asm"
%INCLUDE "source/kernel/features/utils.asm" %INCLUDE "source/kernel/features/utils.asm"
%INCLUDE "source/kernel/features/cli.asm" %INCLUDE "source/kernel/features/cli.asm"
%INCLUDE "source/kernel/features/misc.asm" %INCLUDE "source/kernel/features/misc.asm"
%INCLUDE "source/kernel/features/basic.asm" %INCLUDE "source/kernel/features/basic.asm"
; PROGRAMS
%INCLUDE "source/kernel/programs/ed.asm"
; DATA/VARIABLES ; DATA/VARIABLES
%INCLUDE "source/kernel/data.asm" %INCLUDE "source/kernel/data.asm"

View File

@@ -0,0 +1,279 @@
; Planned commands:
; [ ] i insert
; [ ] a append
; [-] d delete
; [x] l prints lines
; [ ] w save to disk
; [x] q quit
ed:
pusha
call determine_line_count
.main_loop:
; CLEAR VARIABLES
mov [ed_start_int], 0
mov [ed_end_int], 0
mov [ed_operation_from], 0
mov [ed_operation_by], 0
; Setup prompt
mov ax, ed_prompt
mov bx, 40
call keyboard_display_input ; AX = string location, BX = max prompt length
cmp bx, 1 ; I user pressed escape
je .quit
mov si, ed_prompt
mov bx, 0 ; Keeps track of whether comma has passed
jmp .get_token
.error:
call ed_error
jmp .main_loop
; Types of tokens:
; Number: eg 123
; Doller (refers to the last line) $
; Comma ,
; Command: eg i
; eg 123,127i
.get_token:
lodsb
; COMMA
cmp al, ','
je .comma
; DOLLAR SIGN
cmp al, '$'
je .dollar
; NUMBER
call check_is_number
jc .get_number_token
; COMMAND
call check_is_letter
jc .get_letter_token
jmp .error
; Assign a number to either the start or end int (start,end)
.dollar:
mov ax, [ed_line_count]
inc si ; Cancel out the last dec si
jmp .after_int_cast
.get_number_token:
dec si
call string_cast_to_int ; AX = integer, DX = length of int string
.after_int_cast:
cmp bx, 0
je .assign_start_int
jg .assign_end_int
.assign_start_int:
mov [ed_start_int], ax
jmp .after_int_assign
.assign_end_int:
mov [ed_end_int], ax
; Check it's not after the end of the file
cmp ax, [ed_line_count]
jg .error
; Check it's not less than the start int
cmp ax, [ed_start_int]
jl .error
.after_int_assign:
dec si
jmp .get_token
; Determines a command
.get_letter_token:
; If ed int
cmp [ed_end_int], 0
je .set_end_int
.after_end_int_check:
cmp al, 'l'
je .list
cmp al, 'd'
je .delete
cmp al, 'q'
je .quit
call ed_error
jmp .main_loop
; If no end int is assigned, set it to the start int
.set_end_int:
cmp bx,0
push ax
jne .end_int_to_end ; If , has been passed
.end_int_to_start_int:
mov ax, [ed_start_int]
mov [ed_end_int], ax
pop ax
jmp .after_end_int_check
.end_int_to_end:
mov ax, [ed_line_count]
mov [ed_end_int], ax
pop ax
jmp .after_end_int_check
; Changes the value from start int to end int
.comma:
mov bx, 1
jmp .get_token
; COMMANDS
; DELETE ;
.delete:
; Adjust the ed line count
mov ax,[ed_end_int]
sub ax,[ed_start_int] ; difference in the lines
inc ax
sub [ed_line_count], ax
; set up registers to shift data left
; Get the byte of where the left shift will start
mov bx, [ed_end_int]
inc bx
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
mov [ed_operation_from], cx
; Get the number of bytes to shift left by
mov bx, [ed_start_int]
call get_byte_of_line
mov ax, [ed_operation_from]
sub ax, cx
mov [ed_operation_by], ax
; Perform the shift
call shift_data_left
; Adjust the file metadata byte count
mov ax, [file_length]
sub ax, [ed_operation_by]
mov [file_length], ax
; Exit
call text_newline
jmp .main_loop
; LIST ;
.list:
; set up registers to print the data
; Get the byte of where the printing will start
mov bx, [ed_start_int]
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
mov si, cx
; Get the number of bytes to print
mov bx,[ed_end_int]
inc bx
call get_byte_of_line
sub cx,si
call text_newline
add si, file_buffer
call text_print_raw
jmp .main_loop
.quit:
popa
jmp os_start_cli
; This could probably go in disk_?
shift_data_left:
; Calculate source pointer
mov si, [ed_operation_by]
add si, file_buffer
; Calculate destination pointer
mov di, si
sub di, [ed_operation_by]
; Loop count
mov cx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
sub cx, ed_operation_by
; Perform the actual left shift
rep movsb
; Override the rest with zeroes
mov cx, [ed_operation_by]
mov al, 0
rep stosb
ret
ed_error:
pusha
call text_newline
mov ah, 0Eh
mov al, '?'
int 10h
call text_newline
popa
ret
; IN: BX = target line
; OUT: CX = relative byte
; TODO fix
get_byte_of_line:
push dx
push si
push ax
mov si, file_buffer
xor dx,dx
xor cx,cx
jmp .increment_line_count
.line_loop:
xor ax,ax
lodsb
inc cx
cmp al, 0Ah
je .increment_line_count
jmp .line_loop
.increment_line_count:
inc dx
cmp dx, bx
jl .line_loop
jmp .exit
.exit:
pop ax
pop si
pop dx
ret
determine_line_count:
mov si, file_buffer
mov dx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
xor cx,cx
.line_count_loop:
lodsb
cmp al, 0Ah
je .increment_line_count
dec dx
cmp dx, 0
jg .line_count_loop
mov [ed_line_count], cx
ret
.increment_line_count:
inc cx
jmp .line_count_loop
ed_data_start: db "ED IS COOL"
ed_prompt: times 40 db 0
ed_start_int: dw 1
ed_end_int: dw 0
ed_line_count: dw 0
ed_operation_from: dw 0
ed_operation_by: dw 0
ed_tmp: dd 0