flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > OS Construction > DIR command not listing past one file

Author
Thread Post new topic Reply to topic
nkeck72



Joined: 28 May 2015
Posts: 83
Location: 0000:7C00
DIR command not listing past one file
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:
Image

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 00h00h07h        ; 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 00h00h09h
        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 ahbyte ptr es:bx
        cmp ah"i"
        jne external_command
        inc bx
        mov ahbyte ptr es:bx
        cmp ah"r"
        jne external_command
        ; We have a dir command
        push cs
        pop ds
        mov ah01h
        mov dxmessage
        int 21h
        ; First thing is first: update the FSB.
        push es
        mov bx1000h
        mov dsbx
        mov ah02h
        mov al01d
        mov ch00h
        mov cl02d             ; CL=02 is the FSB
        mov dh00h
        mov dlbyte [boot_drv]
        mov bx2000h           ; FSB segment
        mov esbx
        mov bx0000h
        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 bx2000h
        mov esbx
        mov bx0007h
list_files_loop:
        ; Now we loop until we find a null, indicating that we have entered empty space.
        ; Find the file fields
        mov ahbyte ptr es:bx
        cmp ah80h
        je  get_file_name_dir
        ; Otherwise, check for null
        cmp ah00h
        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 bx05d
        ; Now print out the file name on its own
        push dx
        push ds
        mov dxbx
        push es
        pop ds
        mov ah01h
        int 21h
        mov ah0Eh
        mov al0Dh
        int 10h
        mov al0Ah
        int 10h
        pop ds
        pop dx
        ; Now go to the end of the field
        sub bx05d
        add bx14d
        ; 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
Post 15 Nov 2016, 23:57
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15233
Location: 1I/╩╗Oumuamua
We can't see what your int 21h code does to the register values. Perhaps you are corrupting es or bx?

BTW: Your file list field appears to be 15 bytes long, but you only add 14 bytes to bx. Also your directory header appears to be 8 bytes long, but you start searching at 7 bytes.
Post 16 Nov 2016, 00:19
View user's profile Send private message Visit poster's website Reply with quote
nkeck72



Joined: 28 May 2015
Posts: 83
Location: 0000:7C00
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 ax0123h
        jne main_func_check
        cmp bx4567h
        jne main_func_check
        cmp cx8910h
        jne main_func_check
        cmp dx0FFFFh
        jne main_func_check
        ;; Now check for the RAM byte (0x9000:0xFFFF)
        push es
        push bx
        mov bx9000h
        mov esbx
        mov ahbyte ptr es:0FFFFh
        pop bx
        pop es
        cmp ah55h
        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 ah00h
        je  install_check       ; Our install check routine for boot time
        cmp ah01h
        je  print_string        ; Our print string function
        cmp ah02h
        je  open_file           ; Open file function
        cmp ah03h
        je  close_file          ; Close file function
        cmp ah04h
        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 ah06h
        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 ax5555h
        iret
        ; This code snippet is provided by SeproMan on the FASM board.
        ; Thanks Sepro! Very Happy
print_string:
        popf
        push ax 
        push cx 
        push si 
        mov ah0Eh ;BIOS teletype 
        mov bh0 ;Display page 0, don't care about BL in video mode 3 
        mov ch0 ;Count characters 
        mov sidx ;DX can't be used to address memory!!! 
print_loop
        mov al, [ds:si
        inc si 
        cmp al0 
        je print_done 
        int 10h 
        inc ch ;Printed a char 
        jmp print_loop 
print_done
        mov bhch ;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 ah02h
        mov al01h
        mov ch00h
        mov dh00h
        mov cl02h
        ; Get the boot drive from the kernel (4th byte in kernel space)
        push ds
        push ax
        mov ax1000h
        mov dsax
        pop ax
        mov dlptr ds:0003h
        pop ds
        mov bx2000h
        mov esbx
        xor bxbx
        int 13h
        jc  disk_error
        popa
        push es
        push bx
        ; Read through DS:DX to find the filename
        mov sidx
        ; AH is pointer to filename char
        xor ahah
open_filename_loop:
        mov albyte ptr ds:si
        ; Check for null
        cmp al00h
        je  done_open_filename_loop
        ; AH=pointer, AL=byte
        mov bxfilename    ; Address of filename, in data area below
        push bx
        push ax
        xor alal
        mov alah
        xor ahah
        ; AX=00<ptr byte>h
        add axbx
        mov bxax
        ;BL=ptr byte
        pop ax
        mov byte ptr cs:bxal
        mov ahbl
        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 bx2000h
        mov esbx
        mov bx0007h
find_files_loop:
        ; Check for a file
        mov ahbyte ptr es:bx
        cmp ah80h
        je  found_field
        ; If there is a null here, then we are in empty spce of the FSB.
        ; Exit just in case.
        cmp ah00h
        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 sifilename
        ; Compare the filenames
cmp_name_loop:
        mov ahbyte ptr es:bx
        mov albyte ptr cs:si
        cmp ah00h
        je  check_end_filename
        cmp ahal
        ; 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 ahal
        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 ahbyte ptr es:bx
        cmp ah80h
        jne go_back_to_80
        ; Get CHS info
        inc bx
        mov chbyte ptr es:bx
        inc bx
        mov dhbyte ptr es:bx
        inc bx
        mov clbyte ptr es:bx
        ; Now the number of blocks
        inc bx
        mov albyte ptr es:bx
        mov byte ptr cs:blocksal
        push ds
        push ax
        mov ax1000h
        mov dsax
        pop ax
        mov dlbyte ptr ds:0003h
        pop ds
        pop es
        pop bx
        mov ah02h
        int 13h
        jc  disk_error
        ; Move the blocks into AL and quit
        mov albyte ptr cs:blocks
        iret
not_right_file:
        ; Somewhere in the filename. Go back to the beginning of the field
        dec bx
        mov ahbyte ptr es:bx
        cmp ah80h
        jne not_right_file
        ; Back to 0x80. Go to byte after 0xff
        add bx13d
        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 sidx
get_char_loop:
        ; Start by getting a char
        mov ah00h
        int 16h
        ; Check to see if AL is a CR
        cmp al0Dh
        je  get_string_done
        ; Otherwise copy the char and begin again
        mov [ds:si], al
        inc si
        mov ah0Eh
        int 10h
        jmp get_char_loop
get_string_done:
        ; Place our NULL, print a return, and exit
        mov byte [ds:si], 00h
        xor sisi
        push ax
        push bx
        mov ah0Eh
        mov al0Dh
        mov bh00h
        int 10h
        mov al0Ah
        int 10h
        pop bx
        pop ax
        iret
nos_version:
        popf
        mov cx"0B"
        iret
kernel_panic:
        ; Turn on all keylights and Halt
        mov dx60h 
        mov al0EDh 
        out dxal
        mov ax00000111b  
        out dxal
        cli
        hlt
        jmp kernel_panic
times 1024-($-$$db 00h


Post 16 Nov 2016, 00:55
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15233
Location: 1I/╩╗Oumuamua
So print_string alters BH thus corrupting BX.
Post 16 Nov 2016, 01:51
View user's profile Send private message Visit poster's website Reply with quote
nkeck72



Joined: 28 May 2015
Posts: 83
Location: 0000:7C00
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.
Post 17 Nov 2016, 14:16
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15233
Location: 1I/╩╗Oumuamua
Inconsistent calling requirements: the cause of many headaches. Wink

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.
Post 17 Nov 2016, 14:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.