diff --git a/bootloader.asm b/bootloader.asm new file mode 100644 index 0000000..3d44d20 --- /dev/null +++ b/bootloader.asm @@ -0,0 +1,160 @@ +USE16 +format binary as 'bin' + +include 'macros.asm' +include 'constants.asm' + +org 7C00h + +start: + mov byte [BOOT_DRIVE], dl + mov ax, [0410h] + mov word [DETECTED_HARDWARE], ax + + cli + xor ax, ax + mov ds, ax + mov es, ax + mov ss, ax + mov sp, 1000h + sti + + mov ax, 3 + int 10h + + mov ax, 1301h + mov cx, 10 + mov bp, loadingdb + xor dx, dx + mov bx, 7 + int 10h + + mov ah, 02h + ; Number of sectors to load + ; mov al, PROGRAM_LENGTH + mov al, 4 + mov dl, [BOOT_DRIVE] + ; Cylinder + mov ch, 0 + ; Head + mov dh, 0 + ; Start sector number + mov cl, 2 + ; Where load + mov bx, functable + int 13h + + jc booterror + + ; call main + jmp secstage + + ; call dbg_halt_cpu + +loadingdb db "Loading..." + +; Print unsigned int +; +; AX - Num to convert +; SI - Where save string +; --- +; SI - Pointer to string with converted num +its: + push cx + push bx + push di + push ax + + mov cx, 0 + mov bx, 10 + mov di, si + +its.push: + mov dx, 0 + div bx + inc cx + push dx + test ax, ax + jnz its.push +its.pop: + pop dx + add dl, '0' + push ax + mov ah, 0Eh + mov al, dl + int 10h + pop ax + inc di + dec cx + jnz its.pop + + pop ax + pop di + pop bx + pop cx + ret + +errcode db 0 +booterror: + mov [errcode], ah + mov ax, 3 + int 10h + mov ax, 1301h + mov bx, 7 + xor dx, dx + mov cx, 13 + mov bp, booterror.message + int 10h + xor ax, ax + mov al, [errcode] + call its + cli + hlt + +booterror.message db "Error! Code: " + +; times 507-($-$$) db 0 +; MBR partition table starting at byte 446 +times 443-($-$$) db 0 +DETECTED_HARDWARE dw 0 +BOOT_DRIVE db 0 + +; partition 1 (contains the kernel code) +boot_indicator: db 0x80 ; mark as bootable +starting_head: db 0x0 +starting_sector: db 0x1 ; bits 5-0 for sector and bits 7-6 are upper bits of cylinder +starting_cylinder: db 0x0 +system_id: db 0x7f ; just some ID that has not been used for anything else by standard +; the last sector of the partition should be 2880 +ending_head: db 1 ; here I assume the maximum number of heads as 255 +ending_sector: db 4 +ending_cylinder: db 0x0 +first_sector_lba: dd 0x1 ; first sector after the bootsector +total_sectors_in_partition: dd 21 ; 2880-1 because first sector is bootsector + +; partitions 2-4 are unused and therefore set to 0 +times 16 db 0 +times 16 db 0 +times 16 db 0 + +db 0x55, 0xAA + + +include 'functable.asm' + +include 'filetable.asm' + +include 'secstage.asm' + +include 'kernel.asm' + +include 'funcs.asm' + +include 'data.asm' + +VIDEO_MODE db 0 + +times 8192-($-$$) db 0 +; times 8400h-($-$$) db 0 + +; include 'programs/calculator.asm' diff --git a/constants.asm b/constants.asm new file mode 100644 index 0000000..e59be64 --- /dev/null +++ b/constants.asm @@ -0,0 +1,11 @@ +INNUM_BUFFER_SIZE equ 5 +SHNUM_BUFFER_SIZE equ 3 +ACTION_BUFFER_SIZE equ 3 +RESULT_BUFFER_SIZE equ 7 +USERINPUT_BUFFER_SIZE equ 64 +ARGUMENT_BUFFER_SIZE equ 16 +FILENAME_BUFFER_SIZE equ 11 + +PROGRAM_ADDRESS equ 1000h +PROGRAM_LENGTH equ 65 ; In sectors, without boot sector +TABLE_SIZE equ 64 diff --git a/data.asm b/data.asm new file mode 100644 index 0000000..dc4a465 --- /dev/null +++ b/data.asm @@ -0,0 +1,117 @@ +greetings db "Welcome to the Command Line (c)Plaza 2022-2023.", 0Dh, 0Ah, \ + "Write help to see list of commands.", 0 + +goodbye db "Uhadi!", 0 + +zx db "0x", 0 +ln db 0Dh, 0Ah, 0 +space db " ", 0 + +print_registers.axd db "AX: 0x", 0 +print_registers.bxd db "BX: 0x", 0 +print_registers.cxd db "CX: 0x", 0 +print_registers.dxd db "DX: 0x", 0 +print_registers.sid db "SI: 0x", 0 +print_registers.did db "DI: 0x", 0 +print_registers.esd db "ES: 0x", 0 +print_registers.dsd db "DS: 0x", 0 +print_registers.ssd db "SS: 0x", 0 +print_registers.fd db "FLAGS: 0x", 0 +print_registers.h db " ", 0 + +cmd.prefix db ">", 0 +cmd.inc_com db "Invalid command or filename. Type 'help' to see more.", 0Dh, 0Ah, 0 +cmd.file_notfound_err db "There are no files with this filename.", 0 + +cmd.cmd_help db "help", 0 +cmd.cmd_help_desc db "Commands:", 0Dh, 0Ah, \ + "mrun - Run program on user offset", 0Dh, 0Ah, \ + "stdfuncs - show standart functions", 0Dh, 0Ah, \ + "showmem - show memory on offset", 0Dh, 0Ah, \ + "writemem - write byte to memory", 0Dh, 0Ah, \ + "loadmem - load from disk to memory with offset", 0Dh, 0Ah, \ + "shutdown - turn off the computer", 0Dh, 0Ah, \ + "rfd - run program from disk", 0Dh, 0Ah, \ + "dir - show files on disk", 0Dh, 0Ah, \ + "rm - remove file", 0Dh, 0Ah, \ + "help - Show this menu", 0 + +cmd.cmd_mrun db "mrun", 0 +cmd.cmd_mrun_desc db "Enter offset>", 0 + +cmd.cmd_stdfuncs db "stdfuncs", 0 +cmd.cmd_stdfuncs_desc db "System functions:", 0 + +cmd.cmd_showmem db "showmem", 0 +cmd.cmd_showmem_usage db "Usage: showmem ", 0 +; cmd.cmd_showmem_desc db "Enter offset>", 0 +; cmd.cmd_showmem_desc1 db "Enter number of lines(16 bytes) to read>", 0 + +cmd.cmd_writemem db "writemem", 0 +cmd.cmd_writemem_desc db "Enter offset>", 0 +cmd.cmd_writemem_desc1 db "Enter value>", 0 + +cmd.cmd_addlink db "addlink", 0 +cmd.cmd_addlink_desc db "Enter size>", 0 +cmd.cmd_addlink_desc1 db "Enter filename>", 0 +cmd.cmd_addlink_usage db "Usage: addlink ", 0 +cmd.cmd_addlink_size db 0 + +cmd.cmd_loadmem db "loadmem", 0 +cmd.cmd_loadmem_desc db "Enter numbers of sectors to read>", 0 +cmd.cmd_loadmem_desc1 db "Enter drive to read>", 0 +cmd.cmd_loadmem_desc2 db "Enter cylinder>", 0 +cmd.cmd_loadmem_desc3 db "Enter head>", 0 +cmd.cmd_loadmem_desc4 db "Enter number from which sector read>", 0 +cmd.cmd_loadmem_desc5 db "Enter offset to load>", 0 +cmd.cmd_loadmem_sectors db 0 +cmd.cmd_loadmem_drive db 0 +cmd.cmd_loadmem_cylinder db 0 +cmd.cmd_loadmem_head db 0 +cmd.cmd_loadmem_loadoffset db 0 +cmd.cmd_loadmem_saveoffset dw 0 +cmd.cmd_loadmem_loaderr db "Error while reading. See error code in AL", 0 + +cmd.cmd_run_nonex db "File is not executable or link is broken", 0 + +cmd.cmd_rfd db "rfd", 0 +cmd.cmd_rfd_desc db "Enter len of program>", 0 +cmd.cmd_rfd_desc1 db "Enter drive>", 0 +cmd.cmd_rfd_desc4 db "Enter first sector>", 0 +cmd.cmd_rfd_locateerr db "There are no any programs at your address", 0 + +cmd.cmd_dir db "dir", 0 + +cmd.cmd_rm db "rm", 0 +cmd.cmd_rm_usage db "Usage: rm ", 0 + +; cmd.cmd_cf db "cf", 0 + +cmd.cmd_exit db "shutdown", 0 + +cmd.cmd_reboot db "reboot", 0 + +cmd.userinput_buf: + times USERINPUT_BUFFER_SIZE db 0 +db 0 + +cmd.userinput_com: + times ARGUMENT_BUFFER_SIZE db 0 +db 0 + +cmd.userinput_arg1: + times ARGUMENT_BUFFER_SIZE db 0 +db 0 + +cmd.userinput_arg2: + times ARGUMENT_BUFFER_SIZE db 0 +db 0 + +cmd.userinput_arg3: + times ARGUMENT_BUFFER_SIZE db 0 +db 0 + +cmd.cmd_mrun_buf: + times INNUM_BUFFER_SIZE db 0 +db 0 +cmd.cmd_mrun_offset dw 0 diff --git a/fasm b/fasm new file mode 100644 index 0000000..bbe35c6 Binary files /dev/null and b/fasm differ diff --git a/filetable.asm b/filetable.asm new file mode 100644 index 0000000..7f7955f --- /dev/null +++ b/filetable.asm @@ -0,0 +1,8 @@ +filetable: + filetable_ff db 0, 0, 6, 11, "kernel.bin", 0, 0 ; Cylinder, Head, Sector, Size, Name + db 0, 0, 17, 1, "calc.bin", 0, 0, 0, 0 + db 0, 0, 18, 2, "viewer.bin", 0, 0 + db 0, 1, 2, 1, 'null.bin', 0, 0, 0, 0 + db 0, 1, 3, 1, "snake.bin", 0, 0, 0 + +times 2048-($-$$) db 0 ; 1024 bytes \ No newline at end of file diff --git a/funcs.asm b/funcs.asm new file mode 100644 index 0000000..caf8f9e --- /dev/null +++ b/funcs.asm @@ -0,0 +1,846 @@ +; Clear the screen and set cursor position to (0, 0) +clear: + push ax + mov ax, 03h + int 10h + mov ax, 200h + xor dx, dx + int 10h + pop ax + ret + +; Detect display. Video mode 0 if no display, +; 1 if monochrome display, 2 if colour display +detect_video: + push ax + + mov ax, 30h + and ax, DETECTED_HARDWARE + + cmp ax, 20h + mov [VIDEO_MODE], 2 + + cmp ax, 30h + mov [VIDEO_MODE], 1 + + pop ax + ret + +; Print terminated string +; +; DS:SI - Pointer on string +print_string: + pusha + mov cx, 1 + mov bh, 0Fh +print_string.print: + lodsb + + cmp al, 0 + je print_string.finish + + call print_symbol + jmp print_string.print +print_string.finish: + popa + ret + +; Split user input on 4 parts by space +split_str_4_space: + push ax + push bx + push cx + push dx + push si + reset_buf cmd.userinput_com, ARGUMENT_BUFFER_SIZE + reset_buf cmd.userinput_arg1, ARGUMENT_BUFFER_SIZE + reset_buf cmd.userinput_arg2, ARGUMENT_BUFFER_SIZE + reset_buf cmd.userinput_arg3, ARGUMENT_BUFFER_SIZE + mov bx, cmd.userinput_com + mov si, cmd.userinput_buf + +split_str_4_space.lp: + mov al, [si] + mov [bx], al + + inc bx + inc si + + cmp byte [si], ' ' + je split_str_4_space.change_part + cmp byte [si], 0 + je split_str_4_space.rtt + + jmp split_str_4_space.lp +split_str_4_space.rtt: + pop si + pop dx + pop cx + pop bx + pop ax + mov byte [split_str_4_space.part], 1 + ret +split_str_4_space.change_part: + cmp byte [split_str_4_space.part], 1 + je split_str_4_space.change_part.part1 + cmp byte [split_str_4_space.part], 2 + je split_str_4_space.change_part.part2 + cmp byte [split_str_4_space.part], 3 + je split_str_4_space.change_part.part3 + cmp byte [split_str_4_space.part], 4 + je split_str_4_space.change_part.part4 + + split_str_4_space.part db 1 + +split_str_4_space.change_part.part1: + inc [split_str_4_space.part] + mov bx, cmd.userinput_arg1 + inc si + jmp split_str_4_space.lp +split_str_4_space.change_part.part2: + inc [split_str_4_space.part] + mov bx, cmd.userinput_arg2 + inc si + jmp split_str_4_space.lp +split_str_4_space.change_part.part3: + inc [split_str_4_space.part] + mov bx, cmd.userinput_arg3 + inc si + jmp split_str_4_space.lp +split_str_4_space.change_part.part4: + jmp split_str_4_space.rtt + +; Print symbol +; +; AL - symbol +print_symbol: + pusha + + xor bx, bx + mov cx, 1 + mov ah, 0Eh + int 10h + + popa + ret + + +; Reset buffer +; DS:SI - buffer +; CX - Length +reset_buffer: + push si + push cx +reset_buffer.lp: + mov byte [ds:si], 0 + inc si + + dec cx + cmp cx, 0 + jne reset_buffer.lp +reset_buffer.nd: + pop cx + pop si + ret + +; Input string +; +; DS:SI - Pointer on buffer +; CX - Buffer length +; --- +; AX - Last pressed key +input_string: + push bx + mov bx, 0 + + input_string.reset_buffer: + push si + push cx + input_string.reset_buffer.lp: + mov byte [ds:si], 0 + inc si + + dec cx + cmp cx, 0 + jne input_string.reset_buffer.lp + input_string.reset_buffer.nd: + pop cx + pop si + +input_string.processing: + xor ah, ah + int 16h + + cmp al, 0Dh + je input_string.ent + + cmp al, 08h + je input_string.backspace + + cmp al, 03h + je input_string.ctrlc + + call print_symbol + + mov [ds:si+bx], al + inc bx + + cmp bx, cx + je input_string.ent + + jmp input_string.processing +input_string.backspace: + cmp bx, 0 + je input_string.processing + + mov ah, 0Eh + int 10h + + mov al, ' ' + int 10h + + mov al, 08h + int 10h + + dec bx + mov byte [ds:si+bx], 0 + + jmp input_string.processing +input_string.ent: + pop bx + xor ah, ah + print ln + ret +input_string.ctrlc: + jmp input_string.ent + +; Compare strings +; +; DS:SI - Pointer on first string +; DS:BX - Pointer on second string +; --- +; Carry flag - 1 if strings are not equal +compare_strings: + push ax + push bx + push si +compare_strings.comp: + lodsb + + cmp [bx], al + jne compare_strings.not_equal + cmp al, 0 + je compare_strings.equal + + inc bx + + jmp compare_strings.comp +compare_strings.equal: + clc + jmp compare_strings.return +compare_strings.not_equal: + stc + jmp compare_strings.return +compare_strings.return: + pop si + pop bx + pop ax + ret + +; Copies string +; +; DS:SI - Pointer on memory from where copy +; DS:BX - Pointer on memory where copy +copy_string: + push si + push bx + push ax +copy_string.lp: + lodsb + + cmp al, 0 + je copy_string.ed + + mov byte [bx], al + + inc bx + + jmp copy_string.lp +copy_string.ed: + pop ax + pop bx + pop si + ret + +; Calculate len of string +; +; DS:SI - Pointer on string +; --- +; AX - Len of string +calculate_string_len: + push si + xor ax, ax + push ax +calculate_string_len.lp: + lodsb + cmp al, 0 + je calculate_string_len.ed + + pop ax + inc ax + push ax + + jmp calculate_string_len.lp +calculate_string_len.ed: + pop ax + pop si + ret + +; ------------------------------------------------------------------ +; os_print_digit -- Displays contents of AX as a single digit +; Works up to base 37, ie digits 0-Z +; IN: AX = "digit" to format and print + +os_print_digit: + pusha + + cmp ax, 9 ; There is a break in ASCII table between 9 and A + jle .digit_format + + add ax, 'A'-'9'-1 ; Correct for the skipped punctuation + +.digit_format: + add ax, "0" ; 0 will display as '0', etc. + + mov ah, 0Eh ; May modify other registers + int 10h + + popa + ret + + +; ------------------------------------------------------------------ +; os_print_1hex -- Displays low nibble of AL in hex format +; IN: AL = number to format and print + +os_print_1hex: + pusha + + and ax, 0Fh ; Mask off data to display + call os_print_digit + + popa + ret + +; Print AL in hex +; +; AL - Number to print +os_print_2hex: + pusha + + push ax ; Output high nibble + shr ax, 4 + call os_print_1hex + + pop ax ; Output low nibble + call os_print_1hex + + popa + ret + + +; Print AX in hex +; +; AX - Number to print +print_hex: + pusha + + push ax ; Output high byte + mov al, ah + call os_print_2hex + + pop ax ; Output low byte + call os_print_2hex + + popa + ret + +; Print values of registers to screen +; +; AX, BX, CX, DX, SI, DI, ES, DS, SS, FLAGS - Registers to print +print_registers: + pushf + push ss + push ds + push es + push di + push si + push dx + push cx + push bx + + print print_registers.axd + call print_hex + print print_registers.h + + pop ax + print print_registers.bxd + call print_hex + print print_registers.h, ln + + pop ax + print print_registers.cxd + call print_hex + print print_registers.h + + pop ax + print print_registers.dxd + call print_hex + print print_registers.h, ln + + pop ax + print print_registers.sid + call print_hex + print print_registers.h + + pop ax + print print_registers.did + call print_hex + print print_registers.h, ln + + pop ax + print print_registers.esd + call print_hex + print print_registers.h + + pop ax + print print_registers.dsd + call print_hex + print print_registers.h, ln + + pop ax + print print_registers.ssd + call print_hex + print print_registers.h + + pop ax + print print_registers.fd + call print_hex + print print_registers.h, ln + + ret + +; ------------------------------------------------------------------ +; os_string_to_int -- Convert decimal string to integer value +; IN: SI = string location (max 5 chars, up to '65536') +; OUT: AX = number +string_to_int: + pusha + + mov ax, si ; First, get length of string + call os_string_length + + add si, ax ; Work from rightmost char in string + dec si + + mov cx, ax ; Use string length as counter + + mov bx, 0 ; BX will be the final number + mov ax, 0 + + + ; As we move left in the string, each char is a bigger multiple. The + ; right-most character is a multiple of 1, then next (a char to the + ; left) a multiple of 10, then 100, then 1,000, and the final (and + ; leftmost char) in a five-char number would be a multiple of 10,000 + + mov word [.multiplier], 1 ; Start with multiples of 1 + +.loop: + mov ax, 0 + mov byte al, [si] ; Get character + sub al, 48 ; Convert from ASCII to real number + + mul word [.multiplier] ; Multiply by our multiplier + + add bx, ax ; Add it to BX + + push ax ; Multiply our multiplier by 10 for next char + mov word ax, [.multiplier] + mov dx, 10 + mul dx + mov word [.multiplier], ax + pop ax + + dec cx ; Any more chars? + cmp cx, 0 + je .finish + dec si ; Move back a char in the string + jmp .loop + +.finish: + mov word [.tmp], bx + popa + mov word ax, [.tmp] + + ret + + + .multiplier dw 0 + .tmp dw 0 + + os_string_length: + pusha + + mov bx, ax ; Move location of string to BX + + mov cx, 0 ; Counter + + .more: + cmp byte [bx], 0 ; Zero (end of string) yet? + je .done + inc bx ; If not, keep adding + inc cx + jmp .more + + + .done: + mov word [.tmp_counter], cx ; Store count before restoring other registers + popa + + mov ax, [.tmp_counter] ; Put count back into AX before returning + ret + + .tmp_counter dw 0 + +; Convert unsigned int to string +; +; AX - Num to convert +; SI - Where save string +; --- +; SI - Pointer to string with converted num +int_to_string: + push cx + push bx + push di + push ax + + mov cx, 0 + mov bx, 10 ; Set BX 10, for division and mod + mov di, si ; Get our pointer ready + +int_to_string.push: + mov dx, 0 + div bx ; Remainder in DX, quotient in AX + inc cx ; Increase pop loop counter + push dx ; Push remainder, so as to reverse order when popping + test ax, ax ; Is quotient zero? + jnz int_to_string.push ; If not, loop again +int_to_string.pop: + pop dx ; Pop off values in reverse order, and add 48 to make them digits + add dl, '0' ; And save them in the string, increasing the pointer each time + mov [di], dl + inc di + dec cx + jnz int_to_string.pop + + mov byte [di], 0 ; Zero-terminate string + + mov si, di + pop ax + pop di + pop bx + pop cx + ret + +; Find file on disk from filename +; BX - filename +; --- +; SI - filename position in table +; CF - 1 if file not exist +find_file: + push bx + push ax + push cx + mov cx, TABLE_SIZE + mov si, filetable + add si, 4 + mov [find_file.fn_offset], bx +find_file.lp: + + mov bx, [find_file.fn_offset] + call compare_strings + jnc find_file.found + + dec cx + cmp cx, 0 + je find_fileret + + mov bx, 12 + ; len si + xor ax, ax + sub bx, ax + xchg ax, bx + add si, ax + add si, 4 + ; mov al, [si] + ; cmp al, 0 + je find_fileret + jmp find_file.lp +find_file.found: + sub si, 4 + pop cx + pop ax + pop bx + clc + ret +find_fileret: + xor si, si + pop cx + pop ax + pop bx + stc + ret + + find_file.fn_offset dw 0 + +; Remove file +; BX - filename +; --- +; CF - 1 if file not exist +remove_file: + push ax + push si + push bx + + call find_file + jc remove_file.rtt + + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + add si, 2 + mov dword [si], 0 + + pop bx + pop si + pop ax + ret +remove_file.rtt: + pop bx + pop si + pop ax + ret + +; Append file to FS table +; AL - Cylinder +; AH - Head +; BL - sector +; BH - Size +; SI - Pointer on name (Max 11 chars) +append_file: + pusha + mov [append_file.cylinder], al + mov [append_file.head], ah + mov [append_file.sector], bl + mov [append_file.size], bh + mov word [append_file.name_os], si + mov cx, TABLE_SIZE + mov si, filetable+4 +append_file.lp: + cmp byte [si], 0 + je append_file.write + add si, 16 + dec cx + cmp cx, 0 + je append_file.cannot + jmp append_file.lp +append_file.nd: + popa + ret +append_file.write: + sub si, 4 + mov al, [append_file.cylinder] + mov ah, [append_file.head] + mov bl, [append_file.sector] + mov bh, [append_file.size] + mov byte [si], al + mov byte [si+1], ah + mov byte [si+2], bl + mov byte [si+3], bh + add si, 4 + mov bx, si + mov si, word [append_file.name_os] + call copy_string + clc + call write_table + jmp append_file.nd +append_file.cannot: + stc + jmp append_file.nd + + append_file.cylinder db 0 + append_file.head db 0 + append_file.sector db 0 + append_file.size db 0 + append_file.name_os dw 0 + +; Rename file in FS table +; SI - Filename +; BX - To what filename change +rename_file: + pusha + mov word [rename_file.fst], si + mov word [rename_file.snd], bx + mov bx, si + call find_file + jc rename_file.notfound + add si, 4 + push si + reset_buf si, 12 + pop si + mov bx, si + mov si, word [rename_file.snd] + call copy_string + rename_file.notfound: + popa + ret + + rename_file.fst dw 0 + rename_file.snd dw 0 + +; Read file and load to memory +; SI - File in FS table +; BX - Where load +load_file: + pusha + mov ah, 02h + mov al, [si+3] + mov dl, [BOOT_DRIVE] + mov ch, [si] + mov dh, [si+1] + mov cl, [si+2] + int 13h + popa + ret + + ; loadoffset dw 0 + +; Write file and load to memory +; SI - File in FS table +; CX - Where +save_file: + pusha + popa + ret + +; Read FS table from disk +read_table: + pusha + mov ah, 02h + mov al, 2 + mov dl, [BOOT_DRIVE] + mov ch, 0 + mov dh, 0 + mov cl, 3 + mov bx, filetable + int 13h + popa + ret + +; Write FS table to disk +write_table: + pusha + mov ah, 03h + mov al, 2 + mov dl, [BOOT_DRIVE] + mov ch, 0 + mov dh, 0 + mov cl, 3 + mov bx, filetable + int 13h + popa + ret + + +wait_key: + mov ah, 11h + int 16h + + jnz wait_key.key_pressed + + hlt + jmp wait_key + +wait_key.key_pressed: + mov ah, 10h + int 16h + ret + +; Copy memory from A to B +; SI - A +; BX - B +; CX - Number of bytes to copy +copy_memory: + pusha +copy_memory.lp: + cmp cx, 0 + je copy_memory.nd + lodsb + mov [bx], al + inc bx + dec cx + jmp copy_memory.lp +copy_memory.nd: + popa + ret + +; Get cursor position +; --- +; DL - X +; DH - Y +get_cursor_pos: + push ax + push cx + push bx + mov ah, 03h + xor bx, bx + int 10h + pop bx + pop cx + pop ax + ret + +; Set cursor position +; DL - X +; DH - Y +set_cursor_pos: + push ax + push bx + mov ah, 02h + xor bx, bx + int 10h + pop bx + pop ax + ret + +; Print values of registers and halt cpu +dbg_halt_cpu: + call print_registers + call halt_cpu + +; Shows goodbye message and stops the CPU +halt_cpu: + print ln, goodbye + cli + hlt diff --git a/functable.asm b/functable.asm new file mode 100644 index 0000000..f64aa1e --- /dev/null +++ b/functable.asm @@ -0,0 +1,74 @@ +functable: + + dw clear + dw detect_video + dw print_string + dw print_symbol + dw input_string + dw compare_strings + dw copy_string + dw calculate_string_len + dw os_print_digit + dw os_print_1hex + dw os_print_2hex + dw print_hex + dw print_registers + dw string_to_int + dw int_to_string + dw dbg_halt_cpu + dw halt_cpu + dw its + dw find_file + dw remove_file + dw write_table + dw cmd.userinput_arg1 + dw cmd.userinput_arg2 + dw cmd.userinput_arg3 + dw reset_buffer + dw append_file + dw rename_file + dw load_file + dw save_file + dw wait_key + dw copy_memory + dw get_cursor_pos + dw set_cursor_pos + dw read_table +dw 0 + +times 1024 - ($-$$) db 0 + +; FUNCTABLE EQU 7E00h +; clear EQU word [7E00h] +; detect_video EQU word [7E02h] +; print_string EQU word [7E04h] +; print_symbol EQU word [7E06h] +; input_string EQU word [7E08h] +; compare_strings EQU word [7E0Ah] +; copy_string EQU word [7E0Ch] +; calculate_string_len EQU word [7E0Eh] +; os_print_digit EQU word [7E10h] +; os_print_1hex EQU word [7E12h] +; os_print_2hex EQU word [7E14h] +; print_hex EQU word [7E16h] +; print_registers EQU word [7E18h] +; string_to_int EQU word [7E1Ah] +; int_to_string EQU word [7E1Ch] +; dbg_halt_cpu EQU word [7E1Eh] +; halt_cpu EQU word [7E20h] +; its EQU word [7E22h] +; find_file EQU word [7E24h] +; remove_file EQU word [7E26h] +; write_table EQU word [7E28h] +; arg1 EQU word [7E2Ah] +; arg2 EQU word [7E2Ch] +; arg3 EQU word [7E2Eh] +; reset_buffer EQU word [7E30h] +; append_file EQU word [7E32h] +; rename_file EQU word [7E34h] +; load_file EQU word [7E36h] +; save_file EQU word [7E38h] +; wait_key EQU word [7E3Ah] +; copy_memory EQU word [7E3Ch] +; get_cursor_pos EQU word [7E3Eh] +; set_cursor_pos EQU word [7E40h] \ No newline at end of file diff --git a/help.txt b/help.txt new file mode 100644 index 0000000..d574e5c --- /dev/null +++ b/help.txt @@ -0,0 +1,152 @@ +; Clear the screen and set cursor position to (0, 0) +clear: + +; Detect display. Video mode 0 if no display, +; 1 if monochrome display, 2 if colour display +detect_video: + +; Print terminated string +; +; DS:SI - Pointer on string +print_string: + +; Print symbol +; +; AL - symbol +; print_symbol: + +; Reset buffer +; DS:SI - buffer +; CX - Length +reset_buffer: + +; Input string +; +; DS:SI - Pointer on buffer +; CX - Buffer length +; --- +; AX - Last pressed key +input_string: + +; Compare strings +; +; DS:SI - Pointer on first string +; DS:BX - Pointer on second string +; --- +; Carry flag - 1 if strings are not equal +compare_strings: + +; Copies string +; +; DS:SI - Pointer on memory from where copy +; DS:BX - Pointer on memory where copy +copy_string: + +; Calculate len of string +; +; DS:SI - Pointer on string +; --- +; AX - Len of string +calculate_string_len: + +; ------------------------------------------------------------------ +; os_print_digit -- Displays contents of AX as a single digit +; Works up to base 37, ie digits 0-Z +; IN: AX = "digit" to format and print +os_print_digit: + +; ------------------------------------------------------------------ +; os_print_1hex -- Displays low nibble of AL in hex format +; IN: AL = number to format and print +os_print_1hex: + +; Print AL in hex +; +; AL - Number to print +os_print_2hex: + +; Print AX in hex +; +; AX - Number to print +print_hex: + +; Print values of registers to screen +; +; AX, BX, CX, DX, SI, DI, ES, DS, SS, FLAGS - Registers to print +print_registers: + +; ------------------------------------------------------------------ +; os_string_to_int -- Convert decimal string to integer value +; IN: SI = string location (max 5 chars, up to '65536') +; OUT: AX = number +string_to_int: + +; Convert unsigned int to string +; +; AX - Num to convert +; SI - Where save string +; --- +; SI - Pointer to string with converted num +int_to_string: + +; Find file on disk from filename +; BX - filename +; --- +; SI - filename position in table +; CF - 1 if file not exist +find_file: + +; Remove file +; BX - filename +; --- +; CF - 1 if file not exist +remove_file: + +; Append file to FS table +; AL - Cylinder +; AH - Head +; BL - sector +; BH - Size +; SI - Pointer on name (Max 11 chars) +append_file: + +; Rename file in FS table +; SI - Filename +; BX - To what filename change +rename_file: + +; Read file and load to memory +; SI - File in FS table +; CX - Where load +load_file: + +; Write file and load to memory +; SI - File in FS table +; CX - Where +save_file: + +; Write FS table to disk +write_table: + +; Copy memory from A to B +; SI - A +; BX - B +; CX - Number of bytes to copy +copy_memory: + +; Get cursor position +; --- +; DL - X +; DH - Y +get_cursor_pos: + +; Set cursor position +; DL - X +; DH - Y +set_cursor_pos: + +; Print values of registers and halt cpu +dbg_halt_cpu: + +; Shows goodbye message and stops the CPU +halt_cpu: \ No newline at end of file diff --git a/iso/boot.img b/iso/boot.img new file mode 100644 index 0000000..8a9e14b Binary files /dev/null and b/iso/boot.img differ diff --git a/iso/calc.bin b/iso/calc.bin new file mode 100644 index 0000000..86118b4 Binary files /dev/null and b/iso/calc.bin differ diff --git a/iso/just_text.t b/iso/just_text.t new file mode 100644 index 0000000..7f287b6 --- /dev/null +++ b/iso/just_text.t @@ -0,0 +1,10 @@ +Privet, ti 4udovishe +Novay strok + + + + + + + +Dolistay ahaha diff --git a/iso/notepad.bin b/iso/notepad.bin new file mode 100644 index 0000000..c29ac57 Binary files /dev/null and b/iso/notepad.bin differ diff --git a/iso/os.bin b/iso/os.bin new file mode 100644 index 0000000..e2ace7b Binary files /dev/null and b/iso/os.bin differ diff --git a/iso/snake.bin b/iso/snake.bin new file mode 100644 index 0000000..349af67 Binary files /dev/null and b/iso/snake.bin differ diff --git a/iso/viewer.bin b/iso/viewer.bin new file mode 100644 index 0000000..2f26e0f Binary files /dev/null and b/iso/viewer.bin differ diff --git a/kernel.asm b/kernel.asm new file mode 100644 index 0000000..bb98f4d --- /dev/null +++ b/kernel.asm @@ -0,0 +1,480 @@ +; main: +; call clear +; print greetings +; mainloop: +; print parol + +; input input_data, BUFFER_SIZE + +; cmp_strs right_password, input_data +; jnc correct +; print incorrect_password, ln + +; jmp mainloop + +; correct: +; print password_done +; jmp dbg_halt_cpu + +main: + call clear + print greetings, ln +mainloop: + push ax + xor ax, ax + mov al, [BOOT_DRIVE] + call its + pop ax + print cmd.prefix + + input cmd.userinput_buf, USERINPUT_BUFFER_SIZE + cmp al, 03h + je mainret + call split_str_4_space + + cmp_strs cmd.userinput_com, cmd.cmd_help + jnc command.help + + cmp_strs cmd.userinput_com, cmd.cmd_mrun + jnc command.mrun + + cmp_strs cmd.userinput_com, cmd.cmd_stdfuncs + jnc command.stdfuncs + + cmp_strs cmd.userinput_com, cmd.cmd_showmem + jnc command.showmem + + cmp_strs cmd.userinput_com, cmd.cmd_writemem + jnc command.writemem + + cmp_strs cmd.userinput_com, cmd.cmd_loadmem + jnc command.loadmem + + cmp_strs cmd.userinput_com, cmd.cmd_exit + jnc command.shutdown + + cmp_strs cmd.userinput_com, cmd.cmd_rfd + jnc command.rfd + + cmp_strs cmd.userinput_com, cmd.cmd_dir + jnc command.dir + + cmp_strs cmd.userinput_com, cmd.cmd_rm + jnc command.rm + + cmp_strs cmd.userinput_buf, cmd.cmd_reboot + jnc command.reboot + + ; cmp_strs cmd.userinput_com, cmd.cmd_addlink + ; jnc command.addlink + + len cmd.userinput_com + cmp ax, 0 + je mainloop.continue + + mov bx, cmd.userinput_com + call find_file + jnc command.run + + mainloop.continue: + + print cmd.inc_com + + jmp mainloop +mainret: + ret + +command.help: + print cmd.cmd_help_desc, ln + jmp mainloop + + +command.mrun: + print cmd.cmd_mrun_desc + input cmd.cmd_mrun_buf, INNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + + str_to_i cmd.cmd_mrun_buf + add ax, 7C00h + mov word [cmd.cmd_mrun_offset], ax + call ax + + jmp mainloop + + +command.stdfuncs: + print cmd.cmd_stdfuncs_desc, ln + mov si, functable + push si +command.stdfuncs.lp: + pop si + mov ax, [si] + add si, 2 + push si + cmp ax, 0 + je command.stdfuncsret + sub ax, 7C00h + call its + print space + + pop si + mov ax, [si] + add si, 2 + push si + cmp ax, 0 + je command.stdfuncsret_med + sub ax, 7C00h + call its + print space + + pop si + mov ax, [si] + add si, 2 + push si + cmp ax, 0 + je command.stdfuncsret_med + sub ax, 7C00h + call its + print ln + jmp command.stdfuncs.lp +command.stdfuncsret_med: + print ln + pop si + jmp mainloop +command.stdfuncsret: + pop si + jmp mainloop + + +command.showmem: + len cmd.userinput_arg2 + cmp ax, 0 + je command.showmem_usageret + str_to_i cmd.userinput_arg1 + add ax, 7C00h + mov si, ax + push si + + str_to_i cmd.userinput_arg2 + mov cx, ax + +command.showmem.lp: + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print space + + pop si + mov ax, [si] + xchg ah, al + add si, 2 + push si + call print_hex + print ln + + dec cx + cmp cx, 0 + je mainloop + + jmp command.showmem.lp +command.showmem_usageret: + print cmd.cmd_showmem_usage, ln + jmp mainloop + + +command.writemem: + print cmd.cmd_writemem_desc + input cmd.userinput_buf, INNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + add ax, 7C00h + push ax + + print cmd.cmd_writemem_desc1 + input cmd.userinput_buf, INNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + pop si + + mov [si], ax + jmp mainloop + + +command.loadmem: + print cmd.cmd_loadmem_desc + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_sectors], al + + print cmd.cmd_loadmem_desc1 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_drive], al + + print cmd.cmd_loadmem_desc2 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_cylinder], al + + print cmd.cmd_loadmem_desc3 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_head], al + + print cmd.cmd_loadmem_desc4 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_loadoffset], al + + print cmd.cmd_loadmem_desc5 + input cmd.userinput_buf, INNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov word [cmd.cmd_loadmem_saveoffset], ax + + mov ah, 02h + mov al, byte [cmd.cmd_loadmem_sectors] + mov dl, byte [cmd.cmd_loadmem_drive] + mov ch, byte [cmd.cmd_loadmem_cylinder] + mov dh, byte [cmd.cmd_loadmem_head] + mov cl, byte [cmd.cmd_loadmem_loadoffset] + mov bx, word [cmd.cmd_loadmem_saveoffset] + add bx, 7C00h + int 13h + jc command.loadmem_err + jmp mainloop +command.loadmem_err: + call print_registers + print cmd.cmd_loadmem_loaderr, ln + jmp mainloop + +command.shutdown: + mov ax, 5307h + mov bx, 01h + mov cx, 03h + int 15h + ret + +command.rfd: + print cmd.cmd_rfd_desc + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_sectors], al + + print cmd.cmd_rfd_desc1 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_drive], al + + print cmd.cmd_loadmem_desc2 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_cylinder], al + + print cmd.cmd_loadmem_desc3 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_head], al + + print cmd.cmd_rfd_desc4 + input cmd.userinput_buf, SHNUM_BUFFER_SIZE + cmp al, 03h + je mainloop + str_to_i cmd.userinput_buf + mov byte [cmd.cmd_loadmem_loadoffset], al + + mov ah, 02h + mov al, byte [cmd.cmd_loadmem_sectors] + mov dl, byte [cmd.cmd_loadmem_drive] + mov ch, byte [cmd.cmd_loadmem_cylinder] + mov dh, byte [cmd.cmd_loadmem_head] + mov cl, byte [cmd.cmd_loadmem_loadoffset] + mov bx, PROGRAM_ADDRESS + int 13h + jnc command.rfd_ok + jc command.loadmem_err + +command.rfd_ok: + mov al, byte [PROGRAM_ADDRESS] + cmp al, 0 + je command.rfd_noprog + call PROGRAM_ADDRESS + jmp mainloop +command.rfd_noprog: + print cmd.cmd_rfd_locateerr, ln + jmp mainloop + +command.dir: + + call read_table + + mov si, filetable_ff + mov cx, 64 + add si, 4 +command.dir.lp: + mov al, [si] + cmp al, 0 + jne command.dir.printstring + ; push si + ; call print_string + ; print space + ; pop si + command.dir.continue: + + dec cx + cmp cx, 0 + je command.dirret + + cmp si, 8380h + ja command.dirret + + mov bx, 12 + xor ax, ax + sub bx, ax + xchg ax, bx + add si, ax + add si, 4 + ; mov al, [si] + ; cmp al, 0 + ; je command.dirret + + jmp command.dir.lp +command.dirret: + print ln + jmp mainloop +command.dir.printstring: + push si + call print_string + print space + pop si + jmp command.dir.continue + +command.run: + mov bx, cmd.userinput_com + call find_file + + mov bx, PROGRAM_ADDRESS + call load_file + jc command.loadmem_err + + cmp byte [PROGRAM_ADDRESS], 0x7A + je command.run.run + + print cmd.cmd_run_nonex, ln + + jmp mainloop +command.run.run: + call PROGRAM_ADDRESS+1 + jmp mainloop + +command.rm: + len cmd.userinput_arg1 + cmp ax, 0 + je command.rm.usage + + mov bx, cmd.userinput_arg1 + + call remove_file + + jc command.rm.notfound + + call write_table + + jmp mainloop +command.rm.notfound: + print cmd.file_notfound_err, ln + jmp mainloop +command.rm.usage: + print cmd.cmd_rm_usage, ln + jmp mainloop + +; command.addlink: +; len cmd.userinput_arg3 +; cmp ax, 0 +; je command.addlink.usage +; print cmd.cmd_addlink_desc +; input cmd.userinput_buf, SHNUM_BUFFER_SIZE +; str_to_i cmd.userinput_buf +; mov [cmd.cmd_addlink_size], al +; print cmd.cmd_addlink_desc1 +; input cmd.userinput_buf, FILENAME_BUFFER_SIZE +; jmp mainloop +; command.addlink.usage: +; print usage, ln +; jmp mainloop + +command.reboot: + jmp 0xFFFF:0 \ No newline at end of file diff --git a/macros.asm b/macros.asm new file mode 100644 index 0000000..2d6d859 --- /dev/null +++ b/macros.asm @@ -0,0 +1,71 @@ +macro print [pointer] +{ + mov si, pointer + call print_string +} + +macro printh [num] +{ + mov ax, num + call print_hex +} + +macro printi [num] +{ + mov ax, num + call its +} + +macro cmp_strs ptr1, ptr2 +{ + mov si, ptr1 + mov bx, ptr2 + call compare_strings +} + +macro cp_str ptr1, ptr2 +{ + mov si, ptr1 + mov bx, ptr2 + call copy_string +} + +macro input pointer, length +{ + mov si, pointer + mov cx, length + call input_string +} + +macro len pointer +{ + mov si, pointer + call calculate_string_len +} + +macro muln num1, num2 +{ + mov ax, num1 + mov bx, num2 + mul bx +} + +macro str_to_i pointer +{ + mov si, pointer + call string_to_int +} + +macro i_to_str pointer, number +{ + mov si, pointer + mov ax, number + call int_to_string +} + +macro reset_buf pointer, length +{ + mov si, pointer + mov cx, length + call reset_buffer +} diff --git a/programs/calculator.asm b/programs/calculator.asm new file mode 100644 index 0000000..50e77f6 --- /dev/null +++ b/programs/calculator.asm @@ -0,0 +1,232 @@ +; USE16 +; format binary as 'bin' + +; include "include.asm" + +; INNUM_BUFFER_SIZE equ 5 +; ACTION_BUFFER_SIZE equ 3 +; RESULT_BUFFER_SIZE equ 7 +; USERINPUT_BUFFER_SIZE equ 10 + +; include 'programmacros.asm' + +; org 1000h + +; db 0x7A + +; FUNCTABLE EQU 7E00h +; clear EQU word [7E00h] +; detect_video EQU word [7E02h] +; print_string EQU word [7E04h] +; print_symbol EQU word [7E06h] +; input_string EQU word [7E08h] +; compare_strings EQU word [7E0Ah] +; copy_string EQU word [7E0Ch] +; calculate_string_len EQU word [7E0Eh] +; os_print_digit EQU word [7E10h] +; os_print_1hex EQU word [7E12h] +; os_print_2hex EQU word [7E14h] +; print_hex EQU word [7E16h] +; print_registers EQU word [7E18h] +; string_to_int EQU word [7E1Ah] +; int_to_string EQU word [7E1Ch] +; dbg_halt_cpu EQU word [7E1Eh] +; halt_cpu EQU word [7E20h] + + +; print calcgreetings +; pusha +; calcloop: +; print firstn +; input first_num_buf, INNUM_BUFFER_SIZE +; cmp al, 03h +; je calcret + +; print secondn +; input second_num_buf, INNUM_BUFFER_SIZE +; cmp al, 03h +; je calcret + +; str_to_i first_num_buf +; mov word [first_num], ax + +; str_to_i second_num_buf +; mov word [second_num], ax + +; print actionn +; input action_buf, ACTION_BUFFER_SIZE +; cmp_strs action_buf, action_add +; jnc do_add + +; cmp_strs action_buf, action_sub +; jnc go_sub + +; cmp_strs action_buf, action_and +; jnc go_and + +; cmp_strs action_buf, action_or +; jnc go_or + +; cmp_strs action_buf, action_xor +; jnc go_xor + +; print inc_act, ln + +; jmp calcloop +; calcret: +; popa +; ret + +; do_add: +; mov ax, word [first_num] +; mov bx, word [second_num] +; add ax, bx + +; mov si, result_buf +; call int_to_string +; jmp print_res + +; go_sub: +; mov ax, word [first_num] +; mov bx, word [second_num] +; sub ax, bx + +; mov si, result_buf +; call int_to_string +; jmp print_res + +; go_and: +; mov ax, word [first_num] +; mov bx, word [second_num] +; and ax, bx + +; mov si, result_buf +; call int_to_string +; jmp print_res + +; go_or: +; mov ax, word [first_num] +; mov bx, word [second_num] +; or ax, bx + +; mov si, result_buf +; call int_to_string +; jmp print_res + +; go_xor: +; mov ax, word [first_num] +; mov bx, word [second_num] +; xor ax, bx + +; mov si, result_buf +; call int_to_string +; jmp print_res + +; print_res: +; print resultn, result_buf, ln +; jmp calcloop + +; Sdata: +; calcgreetings db "Welcome to the calculator", 0Dh, 0Ah, 0 +; goodbye db "Uhadi!", 0 + +; firstn db "Enter first number:", 0 +; secondn db "Enter second number:", 0 +; actionn db "Enter action:", 0 +; inc_act db "Incrorrect action!", 0 +; resultn db "Result - ", 0 + +; action_add db "add", 0 +; action_sub db "sub", 0 +; action_and db "and", 0 +; action_or db "or" , 0 +; action_xor db "xor", 0 + +; zx db "0x", 0 +; ln db 0Dh, 0Ah, 0 + +; first_num_buf: +; times INNUM_BUFFER_SIZE db 0 +; db 0 +; first_num dw 0 + +; second_num_buf: +; times INNUM_BUFFER_SIZE db 0 +; db 0 +; second_num dw 0 + +; action_buf: +; times ACTION_BUFFER_SIZE db 0 +; db 0 + +; result_buf: +; times RESULT_BUFFER_SIZE db 0 +; db 0 + +include 'include.asm' + +program: + print greetings, ln +.loop: + print prefix_1 + input innum_buffer, INNUM_BUFFER_SIZE + cmp al, 03h + je .end + str_to_i innum_buffer + push ax + + print prefix_2 + input innum_buffer, INNUM_BUFFER_SIZE + cmp al, 03h + je .end + str_to_i innum_buffer + push ax + + print prefix_act + input innum_buffer, INNUM_BUFFER_SIZE + cmp al, 03h + je .end + + cmp_strs innum_buffer, act_add + jnc do_add + cmp_strs innum_buffer, act_sub + jnc do_sub + cmp_strs innum_buffer, act_div + jnc do_div + cmp_strs innum_buffer, act_mul + jnc do_mul + + pop ax + pop ax + + print inc_act, ln + + jmp .loop +.end: + ret + +do_add: + jmp print_result +do_sub: + jmp print_result +do_div: + jmp print_result +do_mul: + jmp print_result +print_result: + jmp program.loop + + greetings db "Welcome to the calculator. List of actions - +-/*", 0 + prefix_1 db "First number>", 0 + prefix_2 db "Second number>", 0 + prefix_act db "Action>", 0 + inc_act db "Incorrect action!", 0 + ln db 0Dh, 0Ah, 0 + act_add db "+", 0 + act_sub db "-", 0 + act_div db "/", 0 + act_mul db "*", 0 + + innum_buffer: + times INNUM_BUFFER_SIZE db 0 + db 0 diff --git a/programs/dskview.asm b/programs/dskview.asm new file mode 100644 index 0000000..6c512ce --- /dev/null +++ b/programs/dskview.asm @@ -0,0 +1,58 @@ +USE16 +include 'programmacros.asm' +format binary as 'bin' + +FUNCTABLE EQU 7E00h +clear EQU word [7E00h] +detect_video EQU word [7E02h] +print_string EQU word [7E04h] +print_symbol EQU word [7E06h] +input_string EQU word [7E08h] +compare_strings EQU word [7E0Ah] +copy_string EQU word [7E0Ch] +calculate_string_len EQU word [7E0Eh] +os_print_digit EQU word [7E10h] +os_print_1hex EQU word [7E12h] +os_print_2hex EQU word [7E14h] +print_hex EQU word [7E16h] +print_registers EQU word [7E18h] +string_to_int EQU word [7E1Ah] +int_to_string EQU word [7E1Ch] +dbg_halt_cpu EQU word [7E1Eh] +halt_cpu EQU word [7E20h] +its EQU word [7E22h] +find_file EQU word [7E24h] +remove_file EQU word [7E26h] +write_table EQU word [7E28h] +arg1 EQU word [7E2Ah] +arg2 EQU word [7E2Ch] +arg3 EQU word [7E2Eh] +reset_buffer EQU word [7E30h] +append_file EQU word [7E32h] +rename_file EQU word [7E34h] +load_file EQU word [7E36h] +save_file EQU word [7E38h] +wait_key EQU word [7E3Ah] +copy_memory EQU word [7E3Ch] + +org 1000h + +start: +mainloop: + print userinput_prefix + input userinput_buf, 30 + cmp al, 03h + je progret + + cmp_strs userinput_buf, loadsector + je loadsector_com + + jmp mainloop +progret: + ret +loadsector_com: + jmp mainloop + + userinput_prefix db '>', 0 + loadsector db "load", 0 + userinput_buf: times 31 db 0 \ No newline at end of file diff --git a/programs/hw.asm b/programs/hw.asm new file mode 100644 index 0000000..e404a6a --- /dev/null +++ b/programs/hw.asm @@ -0,0 +1,6 @@ +include 'include.asm' + +print hw +ret + +hw db "Hello, world", 0Dh, 0Ah, 0 \ No newline at end of file diff --git a/programs/include.asm b/programs/include.asm new file mode 100644 index 0000000..15b424d --- /dev/null +++ b/programs/include.asm @@ -0,0 +1,52 @@ +USE16 +format binary as 'bin' + +include 'programmacros.asm' + +INNUM_BUFFER_SIZE equ 5 +SHNUM_BUFFER_SIZE equ 3 +ACTION_BUFFER_SIZE equ 3 +RESULT_BUFFER_SIZE equ 7 +USERINPUT_BUFFER_SIZE equ 64 +ARGUMENT_BUFFER_SIZE equ 16 +FILENAME_BUFFER_SIZE equ 11 + +FUNCTABLE EQU 7E00h +clear EQU word [7E00h] +detect_video EQU word [7E02h] +print_string EQU word [7E04h] +print_symbol EQU word [7E06h] +input_string EQU word [7E08h] +compare_strings EQU word [7E0Ah] +copy_string EQU word [7E0Ch] +calculate_string_len EQU word [7E0Eh] +os_print_digit EQU word [7E10h] +os_print_1hex EQU word [7E12h] +os_print_2hex EQU word [7E14h] +print_hex EQU word [7E16h] +print_registers EQU word [7E18h] +string_to_int EQU word [7E1Ah] +int_to_string EQU word [7E1Ch] +dbg_halt_cpu EQU word [7E1Eh] +halt_cpu EQU word [7E20h] +its EQU word [7E22h] +find_file EQU word [7E24h] +remove_file EQU word [7E26h] +write_table EQU word [7E28h] +arg1 EQU word [7E2Ah] +arg2 EQU word [7E2Ch] +arg3 EQU word [7E2Eh] +reset_buffer EQU word [7E30h] +append_file EQU word [7E32h] +rename_file EQU word [7E34h] +load_file EQU word [7E36h] +save_file EQU word [7E38h] +wait_key EQU word [7E3Ah] +copy_memory EQU word [7E3Ch] +get_cursor_pos EQU word [7E3Eh] +set_cursor_pos EQU word [7E40h] +read_table EQU word [7E42h] + +org 1000h + +db 0x7A diff --git a/programs/notepad.asm b/programs/notepad.asm new file mode 100644 index 0000000..7550cf0 --- /dev/null +++ b/programs/notepad.asm @@ -0,0 +1,44 @@ +include 'programmacros.asm' + +FUNCTABLE EQU 7E00h +clear EQU word [7E00h] +detect_video EQU word [7E02h] +print_string EQU word [7E04h] +print_symbol EQU word [7E06h] +input_string EQU word [7E08h] +compare_strings EQU word [7E0Ah] +copy_string EQU word [7E0Ch] +calculate_string_len EQU word [7E0Eh] +os_print_digit EQU word [7E10h] +os_print_1hex EQU word [7E12h] +os_print_2hex EQU word [7E14h] +print_hex EQU word [7E16h] +print_registers EQU word [7E18h] +string_to_int EQU word [7E1Ah] +int_to_string EQU word [7E1Ch] +dbg_halt_cpu EQU word [7E1Eh] +halt_cpu EQU word [7E20h] +its EQU word [7E22h] +find_file EQU word [7E24h] +remove_file EQU word [7E26h] +write_table EQU word [7E28h] +arg1 EQU word [7E2Ah] +arg2 EQU word [7E2Ch] +arg3 EQU word [7E2Eh] +reset_buffer EQU word [7E30h] +append_file EQU word [7E32h] +rename_file EQU word [7E34h] + +org 1000h + +start: + print greetings, ln + ret + +2d_input + + + greetings db "Welcome to the notepad!", 0 + zx db "0x", 0 + ln db 0Dh, 0Ah, 0 + space db " ", 0 \ No newline at end of file diff --git a/programs/programmacros.asm b/programs/programmacros.asm new file mode 100644 index 0000000..2d6d859 --- /dev/null +++ b/programs/programmacros.asm @@ -0,0 +1,71 @@ +macro print [pointer] +{ + mov si, pointer + call print_string +} + +macro printh [num] +{ + mov ax, num + call print_hex +} + +macro printi [num] +{ + mov ax, num + call its +} + +macro cmp_strs ptr1, ptr2 +{ + mov si, ptr1 + mov bx, ptr2 + call compare_strings +} + +macro cp_str ptr1, ptr2 +{ + mov si, ptr1 + mov bx, ptr2 + call copy_string +} + +macro input pointer, length +{ + mov si, pointer + mov cx, length + call input_string +} + +macro len pointer +{ + mov si, pointer + call calculate_string_len +} + +macro muln num1, num2 +{ + mov ax, num1 + mov bx, num2 + mul bx +} + +macro str_to_i pointer +{ + mov si, pointer + call string_to_int +} + +macro i_to_str pointer, number +{ + mov si, pointer + mov ax, number + call int_to_string +} + +macro reset_buf pointer, length +{ + mov si, pointer + mov cx, length + call reset_buffer +} diff --git a/programs/snake.asm b/programs/snake.asm new file mode 100644 index 0000000..a3a5a58 --- /dev/null +++ b/programs/snake.asm @@ -0,0 +1,274 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; ;;;;;; ;;;;;; ;; +;; ;; ;; ;; ;; +;; ;; ;; ;;;;;; ;;; ;; ;; ;; ;; ;;; ;; ;; ;;;;;; ;; +;; ;;;;;; ;; ;; ;; ;; ;;;;;;; ;;; ;; ;; ;; ;; ;; ;; ;; +;; ;; ;; ;;;;; ;; ;; ;; ;; ;; ; ;; ;; ;; ;;;; ;;;;;; ;; +;; ;; ;; ;; ;;;;;;; ;; ;; ;; ;;; ;;;;;;; ;; ;; ;; ;; +;; ;; ;; ;;;;;; ;; ;; ;;;;;; ;;;;;; ;; ;; ;; ;; ;; ;; ;;;;;; ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Snake like game writen in x86 real mode assembly. ;; +;; Copyright (C) 2014 Piotr Majkrzak ;; +;; ;; +;; This program is free software: you can redistribute it and/or modify ;; +;; it under the terms of the GNU General Public License as published by ;; +;; the Free Software Foundation, either version 3 of the License, or ;; +;; (at your option) any later version. ;; +;; ;; +;; This program is distributed in the hope that it will be useful, ;; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; +;; GNU General Public License for more details. ;; +;; ;; +;; You should have received a copy of the GNU General Public License ;; +;; along with this program. If not, see . ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; ;; +;; About ;; +;;------- ;; +;; ;; +;; This game is written in Intel's x86 real mode assembly. It is designed ;; +;; to fit in the boot sector, so it must have at most 510 bytes. Therefore, ;; +;; it has very limited functionalities and spaghetti code. You are able to ;; +;; change snake's head direction, eat fruits and restart the game. ;; +;; ;; +;; ;; +;; Assembly ;; +;;---------- ;; +;; ;; +;; To build this code you need to have NASM installed, you can get it from ;; +;; this website: (http://www.nasm.us/). ;; +;; Execute following command: ;; +;; ;; +;; nasm -fbin snake.asm -o snake.bin ;; +;; ;; +;; ;; +;; Launch ;; +;;-------- ;; +;; ;; +;; Now you have `snake.bin` file, which can be installed or loaded into ;; +;; virtual machine like QEMU, which you can get from (www.qemu.org/). ;; +;; ;; +;; qemu-system-i386 snake.bin ;; +;; ;; +;; ;; +;; Gameplay ;; +;;---------- ;; +;; ;; +;; When the game will be launched, you will see huge green rectangle in the ;; +;; middle of the screen. Snake is hidden now in top left corner. To move it ;; +;; you should set its head direction, using arrow keys. If you are stuck or ;; +;; you just want to restart the game, you should press space bar. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +[org 0x1000] + +%DEFINE EMPTY 0b0000_0000 +%DEFINE SNAKE 0b0000_0001 +%DEFINE FRUIT 0b0000_0010 +%DEFINE EATEN 0b0000_0100 +%DEFINE WRECK 0b0000_1000 +%DEFINE DIRUP 0b0001_0000 +%DEFINE DIRDO 0b0010_0000 +%DEFINE DIRLE 0b0100_0000 +%DEFINE DIRRI 0b1000_0000 +%define map(i) byte [es:i] +%define head word [es:1024] +%define tail word [es:1026] +%define fpos word [es:1028] +%define ftim word [es:1030] +%define rand word [es:1032] + +db 0x7A + +init: + .random: + mov ah, 0 + int 0x1A + mov rand, dx + .display: + mov ah, 0x00 + mov al, 0x13 + int 0x10 + .interrupt: + mov [fs:0x08*4], word timer + mov [fs:0x08*4+2], ds + mov [fs:0x09*4], word keyboard + mov [fs:0x09*4+2], ds + + +main: + hlt + jmp main + + +;; () -> (ax); ax,cx,dx +random: + mov ax, rand + mov dx, 7993 + mov cx, 9781 + mul dx + add ax, cx + mov rand, ax + ret + +;; (si) -> (di,ah:al) ; cx,dx +movement: + mov cl, map(si) + mov ax, si + mov dl, 32 + div dl + test cl, DIRUP + jz $+4 + dec al + test cl, DIRDO + jz $+4 + inc al + test cl, DIRLE + jz $+4 + dec ah + test cl, DIRRI + jz $+4 + inc ah + and al, 31 + and ah, 31 + movzx di, al + rol di, 5 + movzx cx, ah + add di,cx + ret + + +keyboard: + in al, 0x60 + mov bx, head + mov ah, map(bx) + cmp al, 0x39 + jne $+12 + mov cx, 1032 + mov al, 0 + mov di, 0 + rep stosb + and ah, 0x0F + cmp al, 0x48 + jne $+5 + or ah, DIRUP + cmp al, 0x50 + jne $+5 + or ah, DIRDO + cmp al, 0x4b + jne $+5 + or ah, DIRLE + cmp al, 0x4d + jne $+5 + or ah, DIRRI + test ah, 0xF0 + jz $+4 + mov map(bx), ah + mov al, 0x61 + out 0x20, al + iret + +timer: + .tick_rtc: + int 0x70 + .move_head: + mov si, head + call movement + mov ah, map(di) + mov al, map(si) + test al, WRECK + jz $+3 + iret + test ah, SNAKE|EATEN + jz $+7 + mov map(si), WRECK + iret + test ah, FRUIT + jz $+20 + mov ftim, 0 + mov fpos, -1 + mov bl, EATEN + jmp $+4 + mov bl, SNAKE + and al, 0xF0 + or bl, al + mov map(di), bl + mov head, di + .move_tail: + mov si, tail + call movement + mov al, map(si) + test al, SNAKE + jz $+11 + mov map(si), EMPTY + mov tail, di + jnz $+9 + and al, 0xF0 + or al, SNAKE + mov map(si), al + .move_fruit: + cmp ftim, 0 + jne $+42 + mov bx, fpos + mov map(bx), EMPTY + call random + mov bx, ax + and bx, 1023 + cmp map(bx), EMPTY + jne $-13 + mov map(bx), FRUIT + mov fpos, bx + mov ftim, 64 + dec ftim + .redraw: + mov cx, 0 + mov ax, cx + mov dl, 32 + div dl + mov bx, ax + movzx ax, bl + add ax, 9 + mov dx, 320 + mul dx + movzx dx, bh + add ax, dx + add ax, 24 + mov dx, 4 + mul dx + mov di, cx + mov dl, map(di) + and dl, 0x0F + cmp dl, EMPTY + jne $+8 + mov ebx, 0x02020202 + cmp dl, SNAKE + jne $+8 + mov ebx, 0x01010101 + cmp dl, FRUIT + jne $+8 + mov ebx, 0x04040404 + cmp dl, EATEN + jne $+8 + mov ebx, 0x05050505 + mov di, ax + mov [gs:di],ebx + add di, 320 + mov [gs:di],ebx + add di, 320 + mov [gs:di],ebx + add di, 320 + mov [gs:di],ebx + inc cx + cmp cx, 1024 + jne .redraw+3 + iret + +times 510-($-$$) db 0 +dw 0AA55h \ No newline at end of file diff --git a/programs/viewer.asm b/programs/viewer.asm new file mode 100644 index 0000000..95c6489 --- /dev/null +++ b/programs/viewer.asm @@ -0,0 +1,72 @@ +include 'include.asm' + +start: + len arg1 + cmp ax, 0 + je progret.usage + mov bx, arg1 + call find_file + jc progret.fnf + mov word [file_FS_offset], si + mov si, file_offset + jmp view_text.prt +progret.usage: + print usage, ln + jmp progret +progret.fnf: + print fnf, ln + jmp progret +progret: + ret + +view_text.prt: + mov word [xpos], 0 + jmp print_symb + view_text.prt.continue: + inc si + jmp view_text.prt +view_text.waiting: + call wait_key + cmp al, 'q' + je progret + jmp view_text.prt + +print_symb: + mov dl, [xpos] + mov dh, [ypos] + cmp dl, 0 + je print_symb.mb_end + print_symb.continue: + mov al, [si] + call print_symbol + pusha + cmp [xpos], 24 + je print_symb.mov_ln + mov al, [xpos] + inc al + mov [xpos], al + print_symb.continue2: + popa + printh word [xpos] + jmp view_text.prt.continue +print_symb.mov_ln: + mov al, [ypos] + inc al + mov [ypos], al + mov byte [xpos], 0 + jmp print_symb.continue2 +print_symb.mb_end: + cmp dh, 25 + je view_text.waiting + jmp print_symb.continue + + usage db "Usage: viewer.bin ", 0 + fnf db "File not found.", 0 + ln db 0Dh, 0Ah, 0 + file_FS_offset dw 0 + xpos db 0 + ypos db 0 + +times 1024-($-$$) db 0 +file_offset: +times 2000 db "A" \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..3ea00fb --- /dev/null +++ b/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +rm iso/os.bin + +echo +echo +./fasm bootloader.asm iso/os.bin +echo +./fasm programs/calculator.asm iso/calc.bin +echo +# ./fasm programs/notepad.asm iso/notepad.bin +# echo +./fasm programs/viewer.asm iso/viewer.bin +echo +nasm -fbin programs/snake.asm -o iso/snake.bin +echo +echo + +cd iso + +rm boot.img +dd if=/dev/zero of=boot.img bs=1024 count=1440 +dd if=os.bin of=boot.img conv=notrunc +dd if=calc.bin of=boot.img conv=notrunc bs=512 seek=16 +# dd if=notepad.bin of=boot.img conv=notrunc bs=512 seek=17 +dd if=viewer.bin of=boot.img conv=notrunc bs=512 seek=17 +dd if=calc.bin of=boot.img bs=512 seek=19 conv=notrunc +dd if=snake.bin of=boot.img bs=512 seek=20 conv=notrunc +# dd if=just_text.t of=boot.img conv=notrunc bs=512 seek=23 + + +cd .. + +# qemu-system-i386 iso/os.bin +qemu-system-i386 -fda iso/boot.img diff --git a/secstage.asm b/secstage.asm new file mode 100644 index 0000000..3a2f65e --- /dev/null +++ b/secstage.asm @@ -0,0 +1,36 @@ +secstage: + mov ah, 02h + mov al, [filetable_ff+3] + mov dl, [BOOT_DRIVE] + mov ch, [filetable_ff] + mov dh, [filetable_ff+1] + mov cl, [filetable_ff+2] + mov bx, main + int 13h + + mov al, [BOOT_DRIVE] + jc .error + + call main + + call dbg_halt_cpu +.error: + cmp cl, 0x0 + je .notfound + cmp cl, 0x20 + je .notfound + jmp booterror + +.notfound: + mov ax, 1301h + mov bx, 7 + xor dx, dx + mov bp, .notfoundmsg + mov cx, 22 + int 10h + cli + hlt + + .notfoundmsg db '"kernel.bin" not found' + +times 2560-($-$$) db 0