flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > DIR command not listing past one file |
Author |
|
nkeck72 15 Nov 2016, 23:57
I have written a builtin command for the NOS kernel, but it seems to only list the first file entry in the FSB before quitting. In this screenshot, I took a photo of the boot disk listing which only lists INT21, however the FSB has two listings. I can't seem to figure out what is wrong with this section of code.
Screenshot of listing: FSB: Code: ;; This is a simple FSB (Filesystem block) for NOS on a 1.44MB floppy disk. ;; PERSONAL NOTE: there are 18 sectors per track, 2 tracks per cyl, and 80 cyl on a 1.44MB floppy ;; CHS for Kernel start db 00h db 00h db 03h ;; Length of kernel in blocks (0FFh here means no kernel on disk) db 04h ;; free blocks dw 2875d ;; total blocks dw 2880d ;; file fields go here ;; INT21 must be our first file here. Otherwise the kernel will not boot. db 80h ; Start of field db 00h, 00h, 07h ; CHS of INT21 db 02h ; INT21 will be 1024 bytes db "INT21", 00h, " " ; Filename and padding db 00h ; EXE flag db 0FFh ; End field ; Example text file for use with type command db 80h db 00h, 00h, 09h db 01h db "text", 00h, " " db 00h db 0FFh times 511-($-$$) db 00h db 0FFh DIR command code: Code: ; pointing at "d" inc bx mov ah, byte ptr es:bx cmp ah, "i" jne external_command inc bx mov ah, byte ptr es:bx cmp ah, "r" jne external_command ; We have a dir command push cs pop ds mov ah, 01h mov dx, message int 21h ; First thing is first: update the FSB. push es mov bx, 1000h mov ds, bx mov ah, 02h mov al, 01d mov ch, 00h mov cl, 02d ; CL=02 is the FSB mov dh, 00h mov dl, byte [boot_drv] mov bx, 2000h ; FSB segment mov es, bx mov bx, 0000h int 13h pop es push cs pop ds ; Now we need to begin the process of listing out the files. ; Start by pointing ES:BX at the first file field. mov bx, 2000h mov es, bx mov bx, 0007h list_files_loop: ; Now we loop until we find a null, indicating that we have entered empty space. ; Find the file fields mov ah, byte ptr es:bx cmp ah, 80h je get_file_name_dir ; Otherwise, check for null cmp ah, 00h je done ; Increment until we find a file inc bx jmp list_files_loop get_file_name_dir: ; The file name is exactly 5 bytes from the 0x80, add that on add bx, 05d ; Now print out the file name on its own push dx push ds mov dx, bx push es pop ds mov ah, 01h int 21h mov ah, 0Eh mov al, 0Dh int 10h mov al, 0Ah int 10h pop ds pop dx ; Now go to the end of the field sub bx, 05d add bx, 14d ; Continue the loop jmp list_files_loop done: ; We are done here. jmp command_prompt The rest of the code, for context, is the repository, in KERNEL.ASM, under the label check_dir. Link is in my signature. _________________ It may look hard, but it won't take long if you take it one byte at a time. NOS: www.github.com/nkeck720/nos |
|||
15 Nov 2016, 23:57 |
|
nkeck72 16 Nov 2016, 00:55
Right, sorry. Here is the INT21 code. I'm not going to be at my computer, so I can't change anything off the bat, but upon a quick visual scan I don't see anything wrong with INT21. I will try changing what is added to BX and check the result when I can get back to it.
Code: use16 ;; ;; This file contains the INT 21 API for the NOS kernel. ;; Table of functions follows: ;; ;; AX=0123h, BX=4567h, CX=8910h, DX=FFFFh: This invokes a kernel panic routine. This is not available ;; to user apps (the NOS kernel will call the panic with CF set and a byte in RAM set to FFh). This ;; sends a message to the user and halts the machine. ;; ;; AH=00h: Does nothing, returns AX=5555h ;; AH=01h: Write string to display (null terminated) from DS:DX, returns number of chars written ;; in BH. ;; AH=02h: Open a file. Opens file whose null-terminated name is in DS:DX, and loads the contents ;; of the file to ES:BX. Returns number of blocks read in AL, CF is set on an error, and ;; BH describes the error when CF is set. ;; AH=03h: Close a file. DS:DX points to the null-terminated file name, ES:BX points to the file ;; contents, and AH contains the number of blocks to be written. Returns nothing on no error, ;; if an error occurs then CF is set and BH describes the error. ;; AH=04h: Gets the NOS version and places two ASCII characters into CX. (e.g. CX="20", NOS 2.0) ;; Minor version number is placed in AL (e.g. Rev 3, AL="3") ;; AH=05h: No function is here yet, this will just IRET until something gets placed here. ;; AH=06h: Gets a string from the user until the user presses return. The string is placed into ;; RAM pointed to by DS:DX. ;; First we want to check if the kernel panic thing is being called. pushf ; For later functions cmp ax, 0123h jne main_func_check cmp bx, 4567h jne main_func_check cmp cx, 8910h jne main_func_check cmp dx, 0FFFFh jne main_func_check ;; Now check for the RAM byte (0x9000:0xFFFF) push es push bx mov bx, 9000h mov es, bx mov ah, byte ptr es:0FFFFh pop bx pop es cmp ah, 55h jne fraud_call ;; Check the carry flag popf jc kernel_panic fraud_call: ;; At this point we can guarantee that this is a fraudulent panic call. Just do an IRET now ;; with the carry flag set. or byte [esp+4], 1 iret main_func_check: ;; Check for a non-panic call. cmp ah, 00h je install_check ; Our install check routine for boot time cmp ah, 01h je print_string ; Our print string function cmp ah, 02h je open_file ; Open file function cmp ah, 03h je close_file ; Close file function cmp ah, 04h je nos_version ; Returns tho NOS version ;; Skip 0x05 for now, created 0x06 with no 0x05! so I will have to think up a ;; function to fill this hole. cmp ah, 06h je get_user_string ; Our getstring function ;; If none of these match, pop our flags, set carry, and return popf ; Set carry or byte [esp+4], 1 iret install_check: ;; This is a simple install check function. ;; Doesn't take any args, and just returns AX=0x5555 popf ; Required of all functions, to keep stack clean mov ax, 5555h iret ; This code snippet is provided by SeproMan on the FASM board. ; Thanks Sepro! print_string: popf push ax push cx push si mov ah, 0Eh ;BIOS teletype mov bh, 0 ;Display page 0, don't care about BL in video mode 3 mov ch, 0 ;Count characters mov si, dx ;DX can't be used to address memory!!! print_loop: mov al, [ds:si] inc si cmp al, 0 je print_done int 10h inc ch ;Printed a char jmp print_loop print_done: mov bh, ch ;BH is be the number of chars that we wrote pop si pop cx pop ax iret open_file: popf pusha ; Load up the FSB mov ah, 02h mov al, 01h mov ch, 00h mov dh, 00h mov cl, 02h ; Get the boot drive from the kernel (4th byte in kernel space) push ds push ax mov ax, 1000h mov ds, ax pop ax mov dl, ptr ds:0003h pop ds mov bx, 2000h mov es, bx xor bx, bx int 13h jc disk_error popa push es push bx ; Read through DS:DX to find the filename mov si, dx ; AH is pointer to filename char xor ah, ah open_filename_loop: mov al, byte ptr ds:si ; Check for null cmp al, 00h je done_open_filename_loop ; AH=pointer, AL=byte mov bx, filename ; Address of filename, in data area below push bx push ax xor al, al mov al, ah xor ah, ah ; AX=00<ptr byte>h add ax, bx mov bx, ax ;BL=ptr byte pop ax mov byte ptr cs:bx, al mov ah, bl pop bx inc si jmp open_filename_loop done_open_filename_loop: ; Increment through the FSB starting at the file fields (8 bytes in) ; File field format: ; 0x80 ; C,H,S of file (3 bytes) ; Number of blocks (1 byte) ; Filename with 0x00 padding (8 bytes) ; Executable flag (1 byte) ; 0xFF mov bx, 2000h mov es, bx mov bx, 0007h find_files_loop: ; Check for a file mov ah, byte ptr es:bx cmp ah, 80h je found_field ; If there is a null here, then we are in empty spce of the FSB. ; Exit just in case. cmp ah, 00h je disk_error inc bx jmp find_files_loop disk_error: ; Otherwise we are done here, and have not found our file. pop bx pop es or byte [esp+4], 1 iret found_field: ; inc through the field to the filename (pointing at 0x80) inc bx inc bx inc bx inc bx inc bx mov si, filename ; Compare the filenames cmp_name_loop: mov ah, byte ptr es:bx mov al, byte ptr cs:si cmp ah, 00h je check_end_filename cmp ah, al ; If not equal then go to the end of the field and check for another one jne not_right_file ; inc and check next char inc bx inc si jmp cmp_name_loop check_end_filename: ; Looking at the end of the file name. If they are the same then we have the correct file and we need ; to load it up. cmp ah, al jne not_right_file ; We have a correct filename. Load it up, point at beginning of file field. go_back_to_80: dec bx mov ah, byte ptr es:bx cmp ah, 80h jne go_back_to_80 ; Get CHS info inc bx mov ch, byte ptr es:bx inc bx mov dh, byte ptr es:bx inc bx mov cl, byte ptr es:bx ; Now the number of blocks inc bx mov al, byte ptr es:bx mov byte ptr cs:blocks, al push ds push ax mov ax, 1000h mov ds, ax pop ax mov dl, byte ptr ds:0003h pop ds pop es pop bx mov ah, 02h int 13h jc disk_error ; Move the blocks into AL and quit mov al, byte ptr cs:blocks iret not_right_file: ; Somewhere in the filename. Go back to the beginning of the field dec bx mov ah, byte ptr es:bx cmp ah, 80h jne not_right_file ; Back to 0x80. Go to byte after 0xff add bx, 13d jmp find_files_loop open_file_data: filename db 00h,00h,00h,00h,00h,00h,00h,00h ; 8 bytes for file name blocks db 00h ; For the number of blocks later close_file: ; Empty for the sake of a test build popf iret get_user_string: popf ; Args: ; DS:DX - address to save string at mov si, dx get_char_loop: ; Start by getting a char mov ah, 00h int 16h ; Check to see if AL is a CR cmp al, 0Dh je get_string_done ; Otherwise copy the char and begin again mov [ds:si], al inc si mov ah, 0Eh int 10h jmp get_char_loop get_string_done: ; Place our NULL, print a return, and exit mov byte [ds:si], 00h xor si, si push ax push bx mov ah, 0Eh mov al, 0Dh mov bh, 00h int 10h mov al, 0Ah int 10h pop bx pop ax iret nos_version: popf mov cx, "0B" iret kernel_panic: ; Turn on all keylights and Halt mov dx, 60h mov al, 0EDh out dx, al mov ax, 00000111b out dx, al cli hlt jmp kernel_panic times 1024-($-$$) db 00h |
|||
16 Nov 2016, 00:55 |
|
revolution 16 Nov 2016, 01:51
So print_string alters BH thus corrupting BX.
|
|||
16 Nov 2016, 01:51 |
|
nkeck72 17 Nov 2016, 14:16
Thanks, I pushed BX before the INT21 calls and popped it back off after and sure enough it works. Thank you! I had completely forgotten that I had added that feature to print_string.
|
|||
17 Nov 2016, 14:16 |
|
revolution 17 Nov 2016, 14:36
Inconsistent calling requirements: the cause of many headaches.
Perhaps you could consider harmonising all the call/return conditions into a single convention? I guarantee you it will make your job a lot easier and less error prone. |
|||
17 Nov 2016, 14:36 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.