From 245cfa57f317e9da4aaca9f1f371d131acd75e87 Mon Sep 17 00:00:00 2001 From: deadvey Date: Wed, 11 Mar 2026 21:16:52 +0000 Subject: [PATCH] ED: Gotten l (list) working, need to work more on d (delete) as there's a bug with deleting lines that are not line 1. --- data/test.asm | 2 + source/kernel/features/cli.asm | 12 +- source/kernel/features/disk.asm | 5 +- source/kernel/features/keyboard.asm | 5 +- source/kernel/features/strings.asm | 25 +-- source/kernel/features/text.asm | 18 +- source/kernel/features/utils.asm | 6 +- source/kernel/programs/ed.asm | 245 +++++++++++++++++++++------- 8 files changed, 234 insertions(+), 84 deletions(-) create mode 100644 data/test.asm diff --git a/data/test.asm b/data/test.asm new file mode 100644 index 0000000..7d9f86a --- /dev/null +++ b/data/test.asm @@ -0,0 +1,2 @@ +X = 100 +PRINT X diff --git a/source/kernel/features/cli.asm b/source/kernel/features/cli.asm index 5036b3c..24c0e1a 100644 --- a/source/kernel/features/cli.asm +++ b/source/kernel/features/cli.asm @@ -1,5 +1,6 @@ os_start_cli: pusha + call os_print_newline @@ -67,14 +68,14 @@ os_read_cli: call os_compare_strings cmp cl, 1 je .ls - - ; ED + + ;ED mov si, user_input mov di, ed_string call os_compare_strings cmp cl, 1 je .ed - + jmp .unkown .unkown: @@ -85,6 +86,11 @@ os_read_cli: jmp .finish .finish: + ; Clear the user input + mov al, 0 + mov cx, 20 + mov di,user_input + repe stosb popa call os_start_cli diff --git a/source/kernel/features/disk.asm b/source/kernel/features/disk.asm index 77244c2..65ad4f3 100644 --- a/source/kernel/features/disk.asm +++ b/source/kernel/features/disk.asm @@ -171,7 +171,7 @@ disk_clear_output_buffer: ; OUT ; data_buffer: file contents ; TODO use predefined data for calculations -; carry flag: set if failed to load file +; CX = 0 if failed to load disk_load_file: pusha call string_length ; cl = string length @@ -235,10 +235,11 @@ disk_load_file: jmp .done_fail .done_fail: popa - stc + mov bx, 1 ret .done: popa + xor bx,bx ret ; Write data to file diff --git a/source/kernel/features/keyboard.asm b/source/kernel/features/keyboard.asm index ec4067d..3409335 100644 --- a/source/kernel/features/keyboard.asm +++ b/source/kernel/features/keyboard.asm @@ -28,6 +28,8 @@ keyboard_check_key: ; IN: ; AX = output address ; BX = max length +; OUT: +; BX = 1 if escape is pressed keyboard_display_input: pusha mov di, ax @@ -55,14 +57,15 @@ keyboard_display_input: jmp .check_key_pressed .esc_key: - stc popa + mov bx, 1 ret .enter_key: mov al, 0 stosb popa + xor bx,bx ret ; Return to the parent function (whatever that may be) .backspace: diff --git a/source/kernel/features/strings.asm b/source/kernel/features/strings.asm index 384c8ef..05da70b 100644 --- a/source/kernel/features/strings.asm +++ b/source/kernel/features/strings.asm @@ -106,39 +106,42 @@ string_join: ret ; ------------------------------------------------------------------------ -; TODO ; Converts a string to an integer ; 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: - pusha + push cx + push bx + push dx xor cx,cx .loop: xor ax,ax lodsb - cmp al, 30h + ; Exit if the character is not a number + cmp al,'0' jl .finish - cmp al, 39h + cmp al,'9' jg .finish - - sub al, 30h + + sub al, '0' mov bx, ax + mov ax, 10 mul cx ; Multiple the current value by 10 add ax, bx ; Then add the new digit mov cx, ax jmp .loop .finish: - mov [int_tmp], cx - popa - mov ax, [int_tmp] + mov ax,cx + pop dx + pop bx + pop cx ret ; ------------------------------------------------------------------------ ; IN: AX = integer (unsigned) ; OUT: AX -> null-terminated string - string_cast_from_int: pusha cld ; Write backwards diff --git a/source/kernel/features/text.asm b/source/kernel/features/text.asm index 4de53c9..9fce0b0 100644 --- a/source/kernel/features/text.asm +++ b/source/kernel/features/text.asm @@ -55,10 +55,16 @@ text_print_raw: je .space cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL je .new_line + cmp al, 09h ; TAB + je .tab cmp al, 0Dh je .repeat int 10h jmp .repeat + .tab: + mov al, ' ' + int 10h + jmp .repeat .space: mov al, 20h int 10h @@ -68,9 +74,6 @@ text_print_raw: int 10h mov al, 0Dh int 10h - push ax - call os_read_input ; wait until key is pressed until it prints the next line - pop ax jmp .repeat .finish: popa @@ -132,6 +135,15 @@ os_set_text_mode: mov dh, 0 mov dl, 0 int 10h + +text_newline: + pusha + mov ax,0E0Ah + int 10h + mov al,0Dh + int 10h + popa + ret popa ret diff --git a/source/kernel/features/utils.asm b/source/kernel/features/utils.asm index edb3943..caab899 100644 --- a/source/kernel/features/utils.asm +++ b/source/kernel/features/utils.asm @@ -7,7 +7,8 @@ util_cat: add si, 4 ; Move si to after 'CAT' call disk_load_file - jc .done ; if file failed to load, just quit + cmp bx, 1 + je .done mov si, file_buffer mov cx, [file_length] @@ -36,7 +37,8 @@ util_basic: ; TODO make this more consistent to account for double spaces ;add si, 3 ; Move si to after 'BAS' call disk_load_file - jc .done + cmp bx, 1 + je .done mov si, file_buffer diff --git a/source/kernel/programs/ed.asm b/source/kernel/programs/ed.asm index f3e8f4b..a54db49 100644 --- a/source/kernel/programs/ed.asm +++ b/source/kernel/programs/ed.asm @@ -1,21 +1,34 @@ ; Planned commands: -; i insert -; a append -; d delete -; l prints lines -; w save to disk -; q quit +; [ ] i insert +; [ ] a append +; [-] d delete +; [x] l prints lines +; [ ] w save to disk +; [x] q quit ed: pusha - call .determine_line_count + 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) $ @@ -29,6 +42,10 @@ ed: cmp al, ',' je .comma + ; DOLLAR SIGN + cmp al, '$' + je .dollar + ; NUMBER call check_is_number jc .get_number_token @@ -36,24 +53,17 @@ ed: ; COMMAND call check_is_letter jc .get_letter_token - - .error: ; Output ? - mov ah, 0Eh - - mov al, '?' - int 10h - mov al, 0Ah - int 10h - mov al, 0Dh - int 10h - - jmp .main_loop + 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: - push si dec si - call string_cast_to_int ; AX = integer + 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 @@ -62,97 +72,208 @@ ed: 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: - pop si + 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 - jmp .get_token + 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 - .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 - jmp .main_loop - .increment_line_count: - inc cx - jmp .line_count_loop ; 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 - mov bx, ed_end_int + ; 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_shift_from], cx + mov [ed_operation_from], cx - mov bx, ed_start_int + ; Get the number of bytes to shift left by + mov bx, [ed_start_int] call get_byte_of_line - mov ax, ed_start_int + mov ax, [ed_operation_from] sub ax, cx - mov [ed_shift_by], ax + 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 - ret + jmp os_start_cli +; This could probably go in disk_? shift_data_left: - mov si, ed_shift_from - mov cx, ed_shift_by - mov di, ed_shift_from - sub di, cx - mov dx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES - .shift_left_loop: - lodsb - stosb - cmp al, 0 - jne .shift_left_loop - jmp ed.main_loop + ; Calculate source pointer + mov si, [ed_operation_by] + add si, file_buffer -; BX = target line + ; 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 - jne .line_loop - inc cx + 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 0 +ed_start_int: dw 1 ed_end_int: dw 0 ed_line_count: dw 0 -ed_shift_from: dw 0 -ed_shift_by: dw 0 +ed_operation_from: dw 0 +ed_operation_by: dw 0 +ed_tmp: dd 0