flat assembler
Message board for the users of flat assembler.

flat assembler > OS Construction > far calls

Author
Thread Post new topic Reply to topic
andy1101



Joined: 05 Jul 2017
Posts: 2
I'm sorry if my question is silly, I'm new to fasm and x86 architecture. I am trying to write a bootloader which loads the second part of bootloader. Everything works pretty fine, i saw in the memory dump that next part of the bootloader has been loaded correctly and i was able to execute code from the next part of bootloader. The problem is that i have difficulties with jmps and calls to the code in the first part of bootloader. I managed to jmp to the code in the first part of bootloader using jmp 0x0000:label. But i still can't call functions from the first part, i tried call far label, call 0x0000:label, far call label etc. Nothing of these worked. So how to implement far calls in fasm in real mode??? (I'm testing my bootloader in bochs by the way).

Here is my code (The next bootloader starts in line 260 (boot2) where i have troubles with calling function from the previous part):


Code:
; kernel's boot loader for x86 architecture
format Binary as "bin"                                                                                                          ;control directive, as "bin" is specifying the default file extension
org 0x7C00                                                                                                                                      ;base address of the code in RAM to calculate labels
jmp boot                                                                                                                                ;unconditional transition to boot main part of boot loader

;header of ListFS
align 4                                                                                                                                         ;next address will be multiple of 4 bytes

fs_magic dd ?                                                                                                                           ;dd - define double word 4 bytes
fs_version dd ?
fs_flags dd ?
fs_base dq ?                                                                                                                            ;dq - define quadro word 8 bytes
fs_size dq ?
fs_map_base dq ?
fs_map_size dq ?
fs_first_file dq ?
fs_uid dq ?
fs_block_size dd ?

;File header

virtual at 0x800
f_info
        f_name rb 256                                                          ;rb - reverse number of bytes
        f_next dq ?
        f_prev dq ?
        f_parent dq ?
        f_flags dq ?
        f_data dq ?
        f_size dq ?
        f_ctime dq ?
        f_mtime dq ?
        f_atime dq ?
end virtual

;data of boot loader                                                                                                                                            ;
label sector_per_track word at $$                                                                                       ; The number of sectors on one track
label head_count byte at $$ + 2                                                                                         ; The number of heads in the drive
label disk_id byte at $$ + 3                                                                                            ; $$ is the base address of code 0x7C00
;boot_msg db "YarzOS boot loader. Version 0.04",13,10,0                                         ; db - define byte right here or array of bytes 
reboot_msg db "Press any key...",13,10,0                                                                        ;13 - new line, 10 - back to the begining 0 - end of string
boot_file_name db "boot.bin",0
;Print function
write_str
        push ax                                                                                                                                 ;save the values of ax data reg and si index reg in steck so they won't be erased
        push si 
        mov ah, 0x0E                                                                                                                    ; ah sets the mode for BIOS int 0x10 function ah=0Eh - Teletype output, al -character
@@                                                                                                                                     ;@ is anonymus label @b - backward @f - forward
        lodsb                                                                                                   ; DSSI --> AL/AX and SI++
        test al, al                                                                                                                         ; check if at least one bit is equal to one 
        jz @f                                                                                                   ;conditional transition if zero condition 
        int 0x10                                                                                                                                ; BIOS int function Video Services
        jmp @b                                                                                                                                  ;return back
@@
        pop si                                                                                                                                  ;grab si and ax old values from steck si and ax go in the opposit order couse steck is FILO memory
        pop ax
        retf
; critical error
error
        pop si
        call write_str
;Reboot
reboot
        mov si,reboot_msg                                                                                                               ;move the address of reboot_msg to SI index reg
        call write_str
        xor ah, ah                                                                                                                              ;ah = 0 - Read key press for BIOS int func 0x16
        int 0x16                                                                                                                                ;BIOS int func 0x16 - Keyboard services
        jmp 0xFFFF0                                                                                                                    ;reboot entry point to BIOS
; Loading of sector DXAX flash in buffer ESDI RAM
load_sector
        cmp bytesector_per_track, 0xFF
        je .use_EDD
        push ax 
        push bx
        push cx
        push dx
        push si
        div sector_per_track                                                                                                  ;DXAX/sector_per_track = AX - quotient DX - excess
        mov cl, dl                                                                                                                              ; quotient is sector number - load it to CL
        inc cl                                                                                                                                  ; Sectors unlike the other things starts with one
        div head_count                                                                                                                ; quotient/head_count 
        mov dh, ah
        mov ch, al
        mov dl, disk_id
        mov bx, di                                                                                                                              ; BX = offset in RAM.  ES=segment already in RAM
        mov al, 1                                                                                                                               ; AL = number of sectors to load
        mov si, 3                                                                                                                               ; Number of trys
 @@
        mov ah, 2                                                                                                                               ; ah = BIOS func number
        int 0x13                                                                                                        
        jnc @f                                                                                                                                  ; error carry flag has been set
        xor ah, ah                                                                                                                              ; ah=0
        int 0x13
        dec si
        jnz @b
 .error
        call error
        db "DISK ERROR",13,10,0
 @@
        pop si 
        pop dx
        pop cx 
        pop bx
        pop ax
        ret
 .use_EDD                                                                                                      ;Enhanced Disk Drive
        push ax 
        push ax
        push dx
        push si
        mov byte0x600, 0x10                                                                   ;loading stracture for BIOS service function 0x10 - 16 bytes the size of the stracture
        mov byte0x601, 0                                                                              ;unused - should be zero
        mov word0x602, 1                                                                              ;Read one sector the number of sectors to be loaded
        mov 0x604, di                                                                                 ;offset
        push es
        pop word0x606                                                                                 ;segmentin RAM
        mov 0x608, ax                                                                                 ;less significant part of sector number on Flash
        mov 0x60A, dx                                                                                 ;most significant part of sector number on Flash
        mov word0x60C, 0                                                                              ;                                                               
        mov word0x60E, 0                                                                              ; 2 Tb max 
        mov ah, 0x42                                                                                    ;code of 0x13 BIOS interrupt func, loading from disk
        mov dl, disk_id                                                                               ;restore disk number for func 
        mov si, 0x600                                                                                   ;the address of stracture for func
        int 0x13                                                                                                ;call the function
        jc .error                                                                                               ; if carry flag is on then an error occured
        pop si 
        pop dx
        pop ax
        ret


; Searching for file with name in DSSI in the catalog in DXAX
find_file
        push cx dx di                                                                                   ; Save the registers
.find
        cmp ax, -1                                                                                          ; Check if we are in the end of the list
        jne @f
        cmp dx, -1
        jne @f
.not_found                                                                                             ; If we have reached it then we should print an error message
        call error
        db "NOT FOUND",13,10,0
 @@
        mov di, f_info
        call load_sector                                                                                ; Load sector with file info
        push di                                                                                                 ; Following is the code of determination of file name length DI = f_info = f_name
        mov cx, 0xFFFF
        xor al, al
        repne scasb                                                                                             ; repne - repeat string operation until not equal scasb scan string - Compare AL with byte at ESEDI and set status flags
        neg cx                                                                                                  ; scasb decrements cx
        dec cx                                                                                                  ; now cx contains the number of bytes in file name                                                                                      
        pop di
        push si                                                                                                 ; compare the names of files
        repe cmpsb                                                                                              ; repe - repeat while equal, cmpsb - compare bytes
        pop si                                          
        je .found                                                                                               ; If it matches then quit
        mov ax, wordf_next                                                                    ; Load the number of next file 
        mov dx, wordf_next + 2
        jmp .find                                                                                               ; Continue the cycle
 .found
        pop di dx cx                                                                                    ; Restore the registers
        ret                                                                                                     ; Quit
        
; Loading of current file into RAM on address in BX0. The number of loaded sectors is in AX
load_file_data
        push bx cx dx si di                                                                     ; Save the registers
        mov ax, wordf_data                                                                    ; Load to DXAX the number of sector with first list of file's sectors
        mov dx, wordf_data + 2
 .load_list    
        cmp ax, -1                                                                                              ; Check if we are in the end of the list
        jne @f
        cmp dx, -1
        jne @f  
 .file_end                                                                                             ; We have loaded the file 
        pop di si dx cx                                                                                 ; Restore all registers exept BX
        mov ax, bx                                                                                              ; Memorize BX
        pop bx                                                                                                  ; Restore its old value
        sub ax, bx                                                                                              ; Find the difference - this will be the size of file in blocks of 16 bytes
        shr ax, 9 - 4                                                                                   ; Convert to sectors
        ret                                                                                                     ; Quit
 @@
        mov di, f_info                                                                                  ; Load the list of file's sectors in the temproraly buffer
        call load_sector
        mov si, di                                                                                              ; SI = DI
        mov cx, 512 / 8 - 1                                                                     ; Number of sectors in the list
 .load_sector
        lodsw                                                                                                   ; Load the next number of sector, lodsw - loads next char into ax or ax,ax
        mov dx, si
        add si, 2
        cmp ax, -1                                                                                              ; Check if we are in the end of the list
        jne @f
        cmp dx, -1
        je .file_end                                                                                    ; If we are in the end then quit
 @@
        push es
        mov es, bx                                                                                              ; Load the next sector to the right address
        call load_sector
        add bx, 0x200 / 16                                                                              ; The address of the next sector is 512 bytes more
        pop es
        loop .load_sector                                                                               ; Данная команда уменьшает CX на 1 и, если он ещё больше нуля, переходит на метку .load_sector
        lodsw                                                                                                   ; Загружаем в DXAX номер следующего списка
        mov dx, si
        jmp .load_list                                                                                  ; Переходим в начало цикла по спискам секторов
        
        
;Boot loader entry point
boot
        jmp 0@f                                                                                                                                ;??? jump to the first @ label of the boot loader 
@@
        mov ax,cs                                                                                                                               ;ax - data reg, cs - code segment reg segment = 512 bytes, ds - data segment reg, es - another data segment reg                                                                                                                               
        mov ds,ax                                                                                                                               ;set to zero all address regs maybe cs = 0 - first code segment
        mov es,ax 
;stack settings
        mov ss,ax                                                                                                                               ;ss - stack segment  = 0 
        mov sp,$$                                                                                                                               ;sp -stack pick , $$ - base address of boot loader set by org 
;enable interrupts
        sti
;memorize the number of boot drive
        mov disk_id,dl
;Prin the message
        ;mov si, boot_msg                                                                                                               ;SI is needed for lodsb
        ;call write_str
;Determining the parameters of boot drive
        mov ah, 0x41
        mov bx, 0x55AA                                                                                                                  ;???
        int 0x13
        jc @f
        mov bytesector_per_track, 0xFF
        jmp .disk_detected
 @@
        mov ah, 0x08                                                                                                                    ;0x0800 - address in Flash to be loaded from 
        xor di, di                                                                                                                              ;offset 
        push es                                                                                                                                 ;ES=segment already
        int 0x13
        pop es
        jc load_sector.error
        inc dh                                                                                                                                  ;load the parameters
        mov head_count, dh
        and cx, 111111b
        mov sector_per_track, cx
 .disk_detected
        ; Loading of the next bootloader
        mov si, boot_file_name
        mov ax, wordfs_first_file
        mov dx, wordfs_first_file + 2
        call find_file
        mov bx, 0x7E00 / 16
        call load_file_data
        ; jump to the next bootloader
        jmp boot2       
;Empty space for boot loader signature 0x55,0xAA
        rb 510 - $ - $$
        db 0x55,0xAA
        
; data for the next bootloader
load_msg_preffix db "Loading '",0
load_msg_suffix db "'...",0
ok_msg db "OK",13,10,0
        ; next bootloader entry point 
boot2
        ; turminating
        mov si, load_msg_preffix                                                                                                                ;SI is needed for lodsb
        call write_str
        jmp 0x0000reboot               
        
; Spliting the string DSSI by slash
split_file_name
        push si
 @@
        lodsb
        cmp al, "/"
        je @f
        jmp @b
 @@
        mov bytesi - 1, 0
        mov ax, si
        pop si
        ret
                
; Loading of the file with name in DSSI in buffer BX0. The size of the file in sectors returns in AX
load_file
        push si
        mov si, load_msg_preffix
        call write_str
        pop si
        call write_str
        push si
        mov si, load_msg_suffix
        call write_str
        pop si
        push si bp
        mov dx, wordfs_first_file + 2
        mov ax, wordfs_first_file
 @@
        push ax
        call split_file_name
        mov bp, ax
        pop ax
        call find_file
        test bytef_flags, 1
        jz @f
        mov si, bp
        mov dx, wordf_data + 2
        mov ax, wordf_data
        jmp @b  
 @@
        call load_file_data
        mov si, ok_msg
        call write_str
        pop bp si
        ret


        

    
Post 07 Jul 2017, 06:23
View user's profile Send private message Reply with quote
Enko



Joined: 03 Apr 2007
Posts: 678
Location: Mar del Plata
I am probably not the best to answer this but as I remember in the far jump the first parameter was the index on the gdt table but that in protecte mode.


For real mode I think this could help:
Quote:
1.2.5 Jumps and calls
The operand of any jump or call instruction can be preceded not only by the size operator, but also by one of the operators specifying type of the jump: short, near of far. For example, when assembler is in 16-bit mode, instruction jmp dword [0] will become the far jump and when assembler is in 32-bit mode, it will become the near jump. To force this instruction to be treated differently, use the jmp near dword [0] or jmp far dword [0] form.

More reference:
here
https://flatassembler.net/docs.php?article=manual#2.1.6
and here
https://flatassembler.net/docs.php?article=manual#1.2.5

Cheers
Post 07 Jul 2017, 15:12
View user's profile Send private message Reply with quote
andy1101



Joined: 05 Jul 2017
Posts: 2
Thank you for replaying, Enko. I read the fasm manual and tried both call dword 0x0000:write_str and call far dword 0x0000:write_str (write_str - is label of my function from the previous part of bootloader), but none of this worked, it seemed that my function hadn't been executed (bochs printed the following message:
[DMA] io write to address 0000000, len=2)

Also as far as i understood i don't need far calls at all cause the code segment limit should be 0x0000ffff, so i guess it means that i'm able to address 0xffff bytes of code.
So why i'm facing troubles with calls from the next part of bootloader?
Post 07 Jul 2017, 16:23
View user's profile Send private message Reply with quote
Enko



Joined: 03 Apr 2007
Posts: 678
Location: Mar del Plata
Wouldnt you need an org instruction in the second bootloader?

As I remember the bios will load the first 512bytes to 0x7C00 .
In the first part of the bootloader you read from the disk and copy it to memory.
If you don´t copy the second part of bootloader to memory the jump will fail because there wouldn´t be nothing after rb 510 - ($ - $$) db 0x55,0xAA

If you do indeed read the second stage of bootloader "boot2:" you should have something like:
Code:
org     0xZZZZZZ
boot2 
; turminating 
        mov si, load_msg_preffix                                                                                                                ;SI is needed for lodsb 
        call write_str 
        jmp 0x0000reboot 
    


I could be wrong of course.
Best regards
Post 07 Jul 2017, 21:52
View user's profile Send private message Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 218
Enko wrote:
Wouldnt you need an org instruction in the second bootloader? ...
I could be wrong of course.
org 0x7C00 plus 512 is the load address (0x7E00) of the second sector.

_________________
Mike Gonta
look and see - many look but few see

http://mikegonta.com
Post 07 Jul 2017, 23:03
View user's profile Send private message Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 218
andy1101 wrote:
So why i'm facing troubles with calls from the next part of bootloader?
Wouldn't it be simpler to call load_sector directly.

_________________
Mike Gonta
look and see - many look but few see

http://mikegonta.com
Post 07 Jul 2017, 23:06
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 261
Location: California
when you inspected memory in your debugger are you SURE that the data you saw was, in fact, the code that should have been there? opcodes require quite a bit of experience to interpret.

it looks like a bug in your CHS calculator.

-Stefan

_________________
byte me.
Post 09 Jul 2017, 08:17
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


Copyright © 1999-2019, Tomasz Grysztar.

Powered by rwasa.