diff --git a/bootloader.nasm b/bootloader.nasm index 60b0027..02a8764 100644 --- a/bootloader.nasm +++ b/bootloader.nasm @@ -20,11 +20,7 @@ start: 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 @@ -47,7 +43,7 @@ start: 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 cl, 0x3 ;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 @@ -226,7 +222,7 @@ times 510-($-$$) db 0 dw 0xAA55 ; => 0x55 0xAA (little endian byte order) ; bootloder debug_mode goes here -times 8192-($-$$) db 0 +times 1024-($-$$) db 0 ; From Version 0.0.3 we are concatinate the bootloader and the kernel after compile time ;%include "kernel.nasm" diff --git a/kernel.nasm b/kernel.nasm index 5f90bb8..f88ca82 100644 --- a/kernel.nasm +++ b/kernel.nasm @@ -6,7 +6,12 @@ start_sing: ; 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 - + ; Setup stack + mov ax, 0x8fc0 + mov ss, ax ; Set 'ss' to this location (the beginning of our stack region) + mov sp, 0xffff ; Set 'ss:sp' to the top of our 8K stack + mov bp, sp + jmp sing_ready %include "mem_lib/mem_lib.nasm" %include "lib/os_lib.nasm" @@ -302,4 +307,4 @@ data: ;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. +times 737280-($-$$)-1024 db 0 ; sector 258 to sector 2048 should be avaliable to the filesystem. diff --git a/lib/os_lib.nasm b/lib/os_lib.nasm index 46f661c..ce5c94d 100644 --- a/lib/os_lib.nasm +++ b/lib/os_lib.nasm @@ -69,4 +69,26 @@ os_clear_screen: int 0x10 popa + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +print_reverse: +; Prints string in si +; IN bx: adress of string +; IN cx: length +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function + ; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] + add bx, cx +.printchar: + mov BYTE al, [bx] ; 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 + cmp cx, 0 + jz .done + int 0x10 ; Otherwise, print the character via 'int 0x10' + dec bx + dec cx + jmp .printchar ; Repeat for the next character +.done: ret \ No newline at end of file diff --git a/lib/svim.nasm b/lib/svim.nasm index 5f1cc44..68ce02d 100644 --- a/lib/svim.nasm +++ b/lib/svim.nasm @@ -1,27 +1,32 @@ BITS 16 +%define svim_starting_row_number_for_text 2 +%define svim_end_row_number_for_text 24 +%define svim_magic_buffer_size 2048 svim: pusha ; save state before program - ;mov si, .os_clear_screen_str - ;call print - xor bx, bx + sub sp, svim_magic_buffer_size + mov [buffer_for_svim_base_left_of_cursor], sp + sub sp, svim_magic_buffer_size + mov [buffer_for_svim_base_right_of_cursor], sp + mov bx, sp + mov BYTE [bx], 0 ; be sure that the first byte is zero. + mov WORD [svim_counter_char_in_left_buffer], 0 ; reset these to zero + mov WORD [svim_counter_char_in_right_buffer], 0 + mov WORD [svim_get_cursor_distance_to_next_line_break], 0 + mov BYTE [svim_save_on_exit], 0 + 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 + xor bx, bx 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 + mov si, welcome_svim_select_file call print call printCRLF - mov si, .seperate_line + mov si, seperate_line call print call vsfs_list_files_command @@ -34,10 +39,10 @@ svim: mov dl, 0x00 ; coloumn zero int 0x10 - mov si, .welcome_svim + mov si, welcome_svim call print call printCRLF - mov si, .welcome_svim_enter_fileindex + mov si, welcome_svim_enter_fileindex call print ; Ask the user for the filename @@ -57,7 +62,7 @@ svim: je .loop_no_push pop cx sub cx, 1 - mov bx, .buffer_for_svim + mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx mov BYTE [bx], 0 ; Go back one space @@ -79,7 +84,7 @@ svim: mov ah, 0x0E int 0x10 ; print char pop cx - mov bx, .buffer_for_svim + mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx mov [bx], al add cx, 1 @@ -92,58 +97,23 @@ svim: .fileindex_done: pop cx ; Cleanup, and now contain filename size mov ax, cx - add ax, .buffer_for_svim + add ax, [buffer_for_svim_base_left_of_cursor] mov bx, ax mov BYTE [bx], 0 - mov si, .buffer_for_svim + mov si, [buffer_for_svim_base_left_of_cursor] call zstring_to_integer ; ax now contain the interger index for the file - mov [.fileindex_for_open_file], ax ; save the file index + mov [fileindex_for_open_file], ax ; save the file index - call os_clear_screen + call svim_redraw_window + ; LOAD FILE + ; Prepare to ask the filesystem to load the file + ; The file system should be given the file_id and the buffer where we can write + mov ax, [fileindex_for_open_file] - ; 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 bx, [buffer_for_svim_base_left_of_cursor] 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) @@ -151,16 +121,45 @@ svim: mov dl, [global_disk_identifier] ;Drive number int 0x13 - mov bx, .buffer_for_svim + mov bx, [buffer_for_svim_base_left_of_cursor] add bx, 2046 mov ax, [bx] - mov [.buffer_counter_svim], ax - ; print buffer - mov si, .buffer_for_svim - mov es, si - call print + mov [svim_counter_char_in_left_buffer], ax .svim_loop: + ; Redraw the whole text, + ; move cursor to the top, where the text has to start (line 2) + xor ax, ax + xor bx, bx + mov ah, 0x02 + mov bh, 0x00 ; page number 0 + mov dh, 0x02 ; row + mov dl, 0x00 ; coloumn + int 0x10 + + mov ax, [svim_counter_char_in_left_buffer] + + mov si, [buffer_for_svim_base_left_of_cursor] + call print + + ; Check if there is somthing to the right of the cursor that should be written to screen + mov cx, [svim_counter_char_in_right_buffer] + cmp cx, 0 ; Nothing to be written + je .no_write_right_of_the_cursor + call get_cursor_position + push dx + mov bx, [buffer_for_svim_base_right_of_cursor] + dec bx + mov cx, [svim_counter_char_in_right_buffer] + call print_reverse + pop dx + xor ax, ax + xor bx, bx + mov ah, 0x02 + mov bx, 0x00 ; page zero + int 0x10 + +.no_write_right_of_the_cursor: xor bx, bx xor cx, cx xor dx, dx @@ -168,45 +167,86 @@ svim: int 0x16 cmp ax, 0x1c0d ; enter key jne .no_enter - mov bx, .buffer_for_svim - add bx, [.buffer_counter_svim] + mov bx, [buffer_for_svim_base_left_of_cursor] + add bx, [svim_counter_char_in_left_buffer] mov BYTE [bx], 13 ; put char in the buffer mov BYTE [bx + 1], 10 ; put char in the buffer - mov bx, [.buffer_counter_svim] + mov bx, [svim_counter_char_in_left_buffer] add bx, 0x02 - mov [.buffer_counter_svim], bx + mov [svim_counter_char_in_left_buffer], bx - xor bx, bx - xor cx, cx - xor dx, dx - mov ax, 0x0e0d - int 0x10 - - mov ax, 0x0e0a - int 0x10 - + call svim_redraw_window jmp .svim_loop .no_enter: + cmp ax, 0x4be0 ; left key + jne .check_up_key + call handle_left_key_pressed + jmp .svim_loop +.check_up_key: + cmp ax, 0x48e0 ; up key + jne .check_right_key + call handle_up_key_pressed + jmp .svim_loop +.check_right_key: + cmp ax, 0x4de0 ; right key + jne .check_down_key + call handle_right_key_pressed + jmp .svim_loop +.check_down_key: + cmp ax, 0x50e0 ; down key + jne .check_tab_key + call handle_down_key_pressed + jmp .svim_loop +.check_tab_key: + cmp ax, 0x0f09 ; tab key + jne .no_special_key_pressed + mov bx, [buffer_for_svim_base_left_of_cursor] + add bx, [svim_counter_char_in_left_buffer] + mov BYTE [bx], 0x20 ; put space char in the buffer + mov BYTE [bx + 1], 0x20 ; put space char in the buffer + mov bx, [svim_counter_char_in_left_buffer] + add bx, 0x02 + mov [svim_counter_char_in_left_buffer], bx + + call svim_redraw_window + jmp .svim_loop + + jmp .svim_loop +.no_special_key_pressed: cmp ax, 0x11b ; ESC key je .end_svim - ;cmp ax, 0x3c00 ; f2 key - ;je .f_key_pushed + cmp ax, 0x3c00 ; f2 key + je .f2_key_pushed + cmp ax, 0x3d00 ; f3 key + je .f3_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, [buffer_for_svim_base_left_of_cursor] + add bx, [svim_counter_char_in_left_buffer] mov [bx], al ; put char in the buffer - mov bx, [.buffer_counter_svim] + mov bx, [svim_counter_char_in_left_buffer] add bx, 0x01 - mov [.buffer_counter_svim], bx + mov [svim_counter_char_in_left_buffer], bx int 0x10 ; print char jmp .svim_loop .end_svim: + mov ax, [svim_counter_char_in_right_buffer] + .copy_data_to_left_buffer: + cmp ax, 0 + je .stop_copy + call handle_right_key_pressed + dec ax + jmp .copy_data_to_left_buffer + .stop_copy: + + mov dl, [svim_save_on_exit] + test dl, dl ; if zero qiut without exit + jz .svim_quit ; save the written buffer ;AH 03h ;AL Sectors To Write Count @@ -215,16 +255,17 @@ svim: ;DH Head ;DL Drive ;ES:BX Buffer Address Pointer - mov ax, [.buffer_counter_svim] - mov bx, .buffer_for_svim + + mov ax, [svim_counter_char_in_left_buffer] + mov bx, [buffer_for_svim_base_left_of_cursor] add bx, 2046 mov [bx], ax mov bx, ds mov es, bx - mov bx, .buffer_for_svim + mov bx, [buffer_for_svim_base_left_of_cursor] - mov ax, [.fileindex_for_open_file] + mov ax, [fileindex_for_open_file] mov ch, al ; move the fileindex in the ch mov ah, 0x03 ;Write sectors to drive @@ -243,34 +284,279 @@ svim: ;mov ah, 0x07 ; scrool down ;mov al, 0x00 ; scrool 0 lines (means blank screen ) ;int 0x10 + +.svim_quit: call os_clear_screen + add sp, svim_magic_buffer_size + add sp, svim_magic_buffer_size popa ret +.f2_key_pushed: + mov al, 1 + mov [svim_save_on_exit], al + call svim_redraw_window + jmp .svim_loop + +.f3_key_pushed: + mov al, 0 + mov [svim_save_on_exit], al + call svim_redraw_window + jmp .svim_loop + .backspace_pushed: - mov bx, [.buffer_counter_svim] + mov bx, [svim_counter_char_in_left_buffer] cmp bx, 0 je .svim_loop - ;print_format .debug_buffer_counter, bx + mov cx, bx - sub cx, 1 - mov bx, .buffer_for_svim + sub cx , 1 + mov bx, [buffer_for_svim_base_left_of_cursor] add bx, cx + + .delete_linebreak: + cmp BYTE [bx], 10 + jne .delete_char 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. + ; cx is already the counter + sub cx, 1 ; Substract one charecter from the buffer, CR and LF + sub bx, 1 + mov BYTE [bx], 0 + mov [svim_counter_char_in_left_buffer], cx + call svim_redraw_window + jmp .svim_loop + + .delete_char: + mov BYTE [bx], 0 + mov [svim_counter_char_in_left_buffer], cx + call svim_redraw_window + jmp .svim_loop + +handle_left_key_pressed: + pusha + mov ax, [svim_counter_char_in_left_buffer] + cmp ax, 0 + je .end + mov bx, [buffer_for_svim_base_left_of_cursor] + add bx, ax + dec bx ; Because it faces the next free spot + mov dx, [bx] + mov BYTE [bx], 0 + push dx + + mov cx, [svim_counter_char_in_right_buffer] + mov bx, [buffer_for_svim_base_right_of_cursor] + add bx, cx + mov [bx], dx + inc bx + mov BYTE [bx], 0 ; be sure that the next byte is always zero + + dec ax + inc cx + mov [svim_counter_char_in_left_buffer], ax + mov [svim_counter_char_in_right_buffer], cx + pop bx + cmp bx, 10 ; check if we hit a line break. + jne .end + call handle_left_key_pressed ; we have hit a linebreak and need to go once more +.end: + popa + ret + +handle_right_key_pressed: + pusha + mov ax, [svim_counter_char_in_right_buffer] + cmp ax, 0 ; check if we have more on the right side of the buffer + je .end ; If we don't, jump to the end and do nothing. + mov bx, [buffer_for_svim_base_right_of_cursor] + add bx, ax + dec bx ; Because it faces the next free spot + + mov dx, [bx] + mov BYTE [bx], 0 + push dx + mov cx, [svim_counter_char_in_left_buffer] + mov bx, [buffer_for_svim_base_left_of_cursor] + add bx, cx + mov [bx], dx + inc bx + mov BYTE [bx], 0 ; be sure that the next byte is always zero + + dec ax + inc cx + mov [svim_counter_char_in_right_buffer], ax + mov [svim_counter_char_in_left_buffer], cx + pop bx + cmp bx, 13 ; check if we hit a line break. + jne .end + call handle_right_key_pressed ; we have hit a linebreak and need to go once more +.end: + popa + ret + +handle_up_key_pressed: + call get_cursor_position ; Find the position of the cursor + xor cx, cx + mov cl, dl ; Store coulun count + push cx ; save the column count. + inc cx +.find_first_line_break: + cmp BYTE cl, 0 + je .find_right_position_on_new_line + call handle_left_key_pressed + dec cl + jmp .find_first_line_break +.find_right_position_on_new_line: + call svim_get_left_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break + mov ax, [svim_get_cursor_distance_to_next_line_break] + pop cx +.move_curser_to_correct_position_on_the_new_line: + cmp cx, ax + jge .end + call handle_left_key_pressed + dec ax + jmp .move_curser_to_correct_position_on_the_new_line +.end: + ret + +handle_down_key_pressed: + call get_cursor_position ; Find the position of the cursor + xor ax, ax + mov al, dl ; Store coulun count + push ax ; save the column count. + call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break + mov cx, [svim_get_cursor_distance_to_next_line_break] +.find_first_line_break: + cmp cx, 0 + je .find_left_position_on_new_line + call handle_right_key_pressed + dec cx + jmp .find_first_line_break + + .find_left_position_on_new_line: + call svim_get_right_line_count ; updates the value in svim_get_cursor_distance_to_next_line_break + mov ax, [svim_get_cursor_distance_to_next_line_break] + pop cx + cmp cx, ax + jle .move_curser_to_correct_position_on_the_new_line + mov cx, ax + .move_curser_to_correct_position_on_the_new_line: + cmp cx, 0 + je .end + call handle_right_key_pressed + dec cx + jmp .move_curser_to_correct_position_on_the_new_line +.end: + ret + +svim_get_left_line_count: + pusha + xor ax, ax ; Number of chars in the right side buffer + xor cx, cx ; This is our counter to the next line break + mov ax, [svim_counter_char_in_left_buffer] + mov bx, [buffer_for_svim_base_left_of_cursor] + add bx, ax + dec bx +.check_next: + cmp ax, 0 ; check if we have hit the absolut beginnig of the string + je .end + mov BYTE dl, [bx] + + cmp BYTE dl, 10 ; See if we have hit an linebreak + je .end_line_break + dec bx ; dec one, to check the prev char, until we hit a line break. + dec ax + inc cx ; add one to the counter + jmp .check_next +.end_line_break: + ;inc cx ; add one to the counter +.end: + mov WORD [svim_get_cursor_distance_to_next_line_break], cx + popa + ret + +svim_get_right_line_count: + pusha + xor ax, ax ; Number of chars in the right side buffer + xor cx, cx ; This is our counter to the next line break + mov ax, [svim_counter_char_in_right_buffer] + mov bx, [buffer_for_svim_base_right_of_cursor] + add bx, ax + dec bx +.check_next: + cmp ax, 0 ; check if we have hit the absolut beginnig of the string + je .end + mov BYTE dl, [bx] + + cmp BYTE dl, 13 ; See if we have hit an linebreak + je .end_line_break + dec bx ; dec one, to check the prev char, until we hit a line break. + dec ax + inc cx ; add one to the counter + jmp .check_next +.end_line_break: + inc cx ; add one to the counter +.end: + mov WORD [svim_get_cursor_distance_to_next_line_break], cx + popa + ret + +get_cursor_position: + xor ax, ax + xor bx, bx + mov ah, 0x03 + mov bh, 0x00 ; page number 0 int 0x10 + ret - ; Place a NULL - mov al, 0x0 ; NULL +svim_redraw_window: + 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 - ; Go back one space again as the above print of NULL pushes the cursor forward again. - mov ax, 0x0e08 + mov si, seperate_line + call print + mov si, welcome_svim + call print + + mov al, [svim_save_on_exit] + test al, al + jz .not_save_mode + mov si, svim_string_save + jmp .after_not_safe_mode +.not_save_mode: + mov si, svim_string_not_save +.after_not_safe_mode: + 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 - jmp .svim_loop + ; 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 + ret ;.f_key_pushed: @@ -280,11 +566,18 @@ svim: ;.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 +svim_get_cursor_offset_on_current_line dw 0 +svim_get_cursor_distance_to_next_line_break dw 0 +buffer_for_svim_base_left_of_cursor dw 0 +buffer_for_svim_base_right_of_cursor dw 0 +svim_counter_char_in_left_buffer dw 0 +svim_counter_char_in_right_buffer dw 0 +seperate_line db '________________________________________________________________________________', 0 +welcome_svim db 'Vim like text editor for SingOS, ESC to exit svim - ', 0 +svim_string_save db 'save-mode', 0 +svim_string_not_save db 'not-save-mode', 0 +welcome_svim_select_file db 'svim v0.2.0 - Open file: ', 0 +welcome_svim_enter_fileindex db 'Enter fileindex: ', 0 +fileindex_for_open_file dw 0 +svim_total_file_size_counter dw 0 +svim_save_on_exit db 0 \ No newline at end of file