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):
; 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 ; [DS:SI] --> 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 0xFFFF:0 ;reboot (entry point to BIOS)
; Loading of sector DX:AX (flash) in buffer ES:DI (RAM)
load_sector:
cmp byte[sector_per_track], 0xFF
je .use_EDD
push ax
push bx
push cx
push dx
push si
div [sector_per_track] ;DX:AX/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 byte[0x600], 0x10 ;loading stracture for BIOS service function 0x10 - 16 bytes the size of the stracture
mov byte[0x601], 0 ;unused - should be zero
mov word[0x602], 1 ;Read one sector (the number of sectors to be loaded)
mov [0x604], di ;offset
push es
pop word[0x606] ;segment(in RAM)
mov [0x608], ax ;less significant part of sector number (on Flash)
mov [0x60A], dx ;most significant part of sector number (on Flash)
mov word[0x60C], 0 ;
mov word[0x60E], 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 DS:SI in the catalog in DX:AX
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 ES:(E)DI 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, word[f_next] ; Load the number of next file
mov dx, word[f_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 BX:0. The number of loaded sectors is in AX
load_file_data:
push bx cx dx si di ; Save the registers
mov ax, word[f_data] ; Load to DX:AX the number of sector with first list of file's sectors
mov dx, word[f_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 ; Загружаем в DX:AX номер следующего списка
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 byte[sector_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, word[fs_first_file]
mov dx, word[fs_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 0x0000:reboot
; Spliting the string DS:SI by slash
split_file_name:
push si
@@:
lodsb
cmp al, "/"
je @f
jmp @b
@@:
mov byte[si - 1], 0
mov ax, si
pop si
ret
; Loading of the file with name in DS:SI in buffer BX:0. 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, word[fs_first_file + 2]
mov ax, word[fs_first_file]
@@:
push ax
call split_file_name
mov bp, ax
pop ax
call find_file
test byte[f_flags], 1
jz @f
mov si, bp
mov dx, word[f_data + 2]
mov ax, word[f_data]
jmp @b
@@:
call load_file_data
mov si, ok_msg
call write_str
pop bp si
ret
|