How do I load my sector with if it's more than 512 bytes?
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
How do I load my sector with if it's more than 512 bytes?
Hello.
How do I load my sector with INT 13h if there is more than 512 bytes? A sector is 512 bytes. Also, could I have some resources for FAT12 please? I've checked out the Wiki. I also checked out things from Microsoft Technet and Wikipedia.
Any help would be appreciated.
Thanks
Steve.
How do I load my sector with INT 13h if there is more than 512 bytes? A sector is 512 bytes. Also, could I have some resources for FAT12 please? I've checked out the Wiki. I also checked out things from Microsoft Technet and Wikipedia.
Any help would be appreciated.
Thanks
Steve.
Re: How do I load my sector with if it's more than 512 bytes
You could if you wanted. The FAT specification is available.stevewoods1986 wrote:Hello.
How do I load my sector with INT 13h if there is more than 512 bytes? A sector is 512 bytes. Also, could I have some resources for FAT12 please? I've checked out the Wiki. I also checked out things from Microsoft Technet and Wikipedia.
Any help would be appreciated.
Thanks
Steve.
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
Re: How do I load my sector with if it's more than 512 bytes
I might look at that. How would I load my sector if there is more than 512 bytes?zaval wrote:You could if you wanted. The FAT specification is available.stevewoods1986 wrote:Hello.
How do I load my sector with INT 13h if there is more than 512 bytes? A sector is 512 bytes. Also, could I have some resources for FAT12 please? I've checked out the Wiki. I also checked out things from Microsoft Technet and Wikipedia.
Any help would be appreciated.
Thanks
Steve.
Re: How do I load my sector with if it's more than 512 bytes
"al" = number of sectors to read.
Quite simple.
For more info see: http://www.ctyme.com/intr/rb-0607.htm
This page: http://wiki.osdev.org/FAT
This page:http://www.maverick-os.dk/FileSystemFor ... ystem.html
This thread: http://forum.osdev.org/viewtopic.php?t=21155
Quite simple.
For more info see: http://www.ctyme.com/intr/rb-0607.htm
This page: http://wiki.osdev.org/FAT
This page:http://www.maverick-os.dk/FileSystemFor ... ystem.html
This thread: http://forum.osdev.org/viewtopic.php?t=21155
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
Re: How do I load my sector with if it's more than 512 bytes
I tried that. Doesn't work. I tried making a file that does lots of operands and including it. I changed al in my bootloader. It just stops my kernel from working. By the way, how would I load my kernel by filename?Octacone wrote:"al" = number of sectors to read.
Quite simple.
For more info see: http://www.ctyme.com/intr/rb-0607.htm
This page: http://wiki.osdev.org/FAT
This page:http://www.maverick-os.dk/FileSystemFor ... ystem.html
This thread: http://forum.osdev.org/viewtopic.php?t=21155
Re: How do I load my sector with if it's more than 512 bytes
Hello,
What do you mean by "making a file that does lots of operands and including it?" Nothing about int 13h involves files. If you are going to use fat12, write a "Read Sector" function that reads only 1 sector. Don't worry about reading "multiple" sectors - with any of the fat filesystems you'll be reading 1 sector at a time.
How are you currently calling this interrupt? What is the expected behavior and what is currently happening? Have you tried just loading 1 sector to some location and verifying that it gets loaded? How have you verified that the function works/does not work? It is helpful to use a hex editor with bochsdbg to compare and test.
Don't worry about file systems until you are able to read sectors. (To answer the question however, you locate the file from the root directory structure which gives you the starting cluster. The fat gives you the next chain of clusters until eof. All of this is in the fat32 whitepaper linked earlier.)
What do you mean by "making a file that does lots of operands and including it?" Nothing about int 13h involves files. If you are going to use fat12, write a "Read Sector" function that reads only 1 sector. Don't worry about reading "multiple" sectors - with any of the fat filesystems you'll be reading 1 sector at a time.
How are you currently calling this interrupt? What is the expected behavior and what is currently happening? Have you tried just loading 1 sector to some location and verifying that it gets loaded? How have you verified that the function works/does not work? It is helpful to use a hex editor with bochsdbg to compare and test.
Don't worry about file systems until you are able to read sectors. (To answer the question however, you locate the file from the root directory structure which gives you the starting cluster. The fat gives you the next chain of clusters until eof. All of this is in the fat32 whitepaper linked earlier.)
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: How do I load my sector with if it's more than 512 bytes
Sectors are always 512 bytes. To load more bytes, you load multiple sectors. So to read 1024 bytes, you need to read two sectors. The simplest way, I find, to do this is to loop your sector-reading function, and for each sector you increment the start sector value (carrying over to the side and/or cylinder/track values if required) and add 512 to the destination address (make sure that you've got enough space to read however much data you're trying to read).
Mine looks like this:I seem to remember that cylinders/tracks are numbered from 1, not 0. EDIT: Sectors are numbered from 1, cylinders/tracks and heads are numbered from 0.
Mine looks like this:
Code: Select all
;read sectors from disk
;ax = start sector, bx = end sector (exclusive), es = destination segment
;updates es to end of data
readsectors:
push cx
push ax
read_loop:
call readsector
mov cx, es
add cx, #0x20
mov es, cx
inc ax
cmp ax, bx
jb read_loop
pop ax
pop cx
ret
;read a sector from disk
;ax = sector, es = destination segment
readsector:
push dx
push cx
push bx
push ax
push ax
mov cl, #36
div cl
mov bl, al
pop ax
mov cl, #18
div cl
and al, #0x01
add ah, #0x01
;bl = cylinder/track, al = head, ah = sector
mov ch, bl
mov cl, ah
mov dh, al
mov dl, #0
mov ax, #0x0201
mov bx, #0x0000
int 0x13
pop ax
pop bx
pop cx
pop dx
ret
Last edited by onlyonemac on Sun Aug 13, 2017 2:17 pm, edited 1 time in total.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Re: How do I load my sector with if it's more than 512 bytes
Except when they aren't. Not really important within the context of this thread, but it would be good to not claim that they always are..onlyonemac wrote:Sectors are always 512 bytes.
As for the OP, seriously, if you know how to read one sector and you can't figure out on your own how to read two or more sectors, then osdev might not be for you... Can't really think of a simpler programming problem to solve than creating a function and calling it twice..
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: How do I load my sector with if it's more than 512 bytes
AFAIK logical sectors are always 512 bytes. Physical sectors can, of course, be any size, but that's a hardware technicality. For standard storage device interfaces/protocols, a "sector" is always 512 bytes, even if you use LBA.LtG wrote:Except when they aren't. Not really important within the context of this thread, but it would be good to not claim that they always are..onlyonemac wrote:Sectors are always 512 bytes.
It's a bit more complicated than that. You also need to change the destination address, and handle crossing over from one side of the disk to the other or moving to the next track. And of course if you're using the BIOS interrupt then you'll probably overlook the idea of even using a subroutine/loop and instead get confused about the built-in ability to read multiple sectors and the various BIOS bugs that affect this function (I believe that this is what happened here).LtG wrote:Can't really think of a simpler programming problem to solve than creating a function and calling it twice..
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
Re: How do I load my sector with if it's more than 512 bytes
So should I do?onlyonemac wrote:AFAIK logical sectors are always 512 bytes. Physical sectors can, of course, be any size, but that's a hardware technicality. For standard storage device interfaces/protocols, a "sector" is always 512 bytes, even if you use LBA.LtG wrote:Except when they aren't. Not really important within the context of this thread, but it would be good to not claim that they always are..onlyonemac wrote:Sectors are always 512 bytes.It's a bit more complicated than that. You also need to change the destination address, and handle crossing over from one side of the disk to the other or moving to the next track. And of course if you're using the BIOS interrupt then you'll probably overlook the idea of even using a subroutine/loop and instead get confused about the built-in ability to read multiple sectors and the various BIOS bugs that affect this function (I believe that this is what happened here).LtG wrote:Can't really think of a simpler programming problem to solve than creating a function and calling it twice..
Code: Select all
mov ah, 2
mov al, 1
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
mov bx, 0x7c00
mov es, bx
mov bx, 0x00
int 13h
mov ah, 2
mov al, 1
mov ch, 0
mov cl, 3
mov dh, 0
mov dl, 0
mov bx, 0x7c00
mov es, bx
mov bx, 0x00
int 13h
jmp 0x7c00:0x00
To add bytes. Make a file with lots of moving that is over 512 bytes and see if my other code works.neon wrote:Hello,
What do you mean by "making a file that does lots of operands and including it?" Nothing about int 13h involves files. If you are going to use fat12, write a "Read Sector" function that reads only 1 sector. Don't worry about reading "multiple" sectors - with any of the fat filesystems you'll be reading 1 sector at a time.
How are you currently calling this interrupt? What is the expected behavior and what is currently happening? Have you tried just loading 1 sector to some location and verifying that it gets loaded? How have you verified that the function works/does not work? It is helpful to use a hex editor with bochsdbg to compare and test.
Don't worry about file systems until you are able to read sectors. (To answer the question however, you locate the file from the root directory structure which gives you the starting cluster. The fat gives you the next chain of clusters until eof. All of this is in the fat32 whitepaper linked earlier.)
Code: Select all
%include "junkymoving.asm"
more code here...
doesn't run :( thats what happens when its more than 512 bytes
-
- Member
- Posts: 1146
- Joined: Sat Mar 01, 2014 2:59 pm
Re: How do I load my sector with if it's more than 512 bytes
I haven't tried your code but at a glance it seems to me that it will write the second sector to the same place that it wrote the first sector. Your secondstevewoods1986 wrote:So should I do?
What do I do?Code: Select all
mov ah, 2 mov al, 1 mov ch, 0 mov cl, 2 mov dh, 0 mov dl, 0 mov bx, 0x7c00 mov es, bx mov bx, 0x00 int 13h mov ah, 2 mov al, 1 mov ch, 0 mov cl, 3 mov dh, 0 mov dl, 0 mov bx, 0x7c00 mov es, bx mov bx, 0x00 int 13h jmp 0x7c00:0x00
Code: Select all
mov bx, 0x7c00
Code: Select all
mov bx, 0x7e00
Also why are you writing to 0x7c00:0x0000, IIRC that will overwrite your bootsector?
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
Re: How do I load my sector with if it's more than 512 bytes
It works. That's why. No problems. I don't think I need 0x7e00 unless I have stack problems... wait. you mean. ohonlyonemac wrote:I haven't tried your code but at a glance it seems to me that it will write the second sector to the same place that it wrote the first sector. Your secondstevewoods1986 wrote:So should I do?
What do I do?Code: Select all
mov ah, 2 mov al, 1 mov ch, 0 mov cl, 2 mov dh, 0 mov dl, 0 mov bx, 0x7c00 mov es, bx mov bx, 0x00 int 13h mov ah, 2 mov al, 1 mov ch, 0 mov cl, 3 mov dh, 0 mov dl, 0 mov bx, 0x7c00 mov es, bx mov bx, 0x00 int 13h jmp 0x7c00:0x00
should probably beCode: Select all
mov bx, 0x7c00
otherwise you'll overwrite (in memory) the first sector with the second sector.Code: Select all
mov bx, 0x7e00
Also why are you writing to 0x7c00:0x0000, IIRC that will overwrite your bootsector?
Re: How do I load my sector with if it's more than 512 bytes
Hello,
The provided code loads to 0x7c000 and 0x7e000 not 0x7c00. However, I suspect this might have not been done intentionally; it might be a good idea for the original poster to review segmentation.
- How are you copying the boot record to the disk image?
- What happens if you load it to 0x7e0:0 and 0x800:0? You should not need a jump since the sectors would be loaded in consecutive memory.
- Where is the stack?
The provided code loads to 0x7c000 and 0x7e000 not 0x7c00. However, I suspect this might have not been done intentionally; it might be a good idea for the original poster to review segmentation.
- How are you copying the boot record to the disk image?
- What happens if you load it to 0x7e0:0 and 0x800:0? You should not need a jump since the sectors would be loaded in consecutive memory.
- Where is the stack?
Last edited by neon on Sun Aug 13, 2017 5:25 pm, edited 1 time in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
- Schol-R-LEA
- Member
- Posts: 1925
- Joined: Fri Oct 27, 2006 9:42 am
- Location: Athens, GA, USA
Re: How do I load my sector with if it's more than 512 bytes
@onlyonemac: I was confused too, until I noticed that the code is setting ES, via BX, and then clearing BX. IOW, it's not not writing to 0000:7c00 (computed absolute address 7c00 hex, or 31,774 decimal), where the BIOS loads the boot sector) but to 7c00:0000 (computed absolute address 7c000, or 507,904 decimal) - which is a much higher, being about 5/6ths of the way towards the top of base RAM memory according to the Memory Map.
You're point about it overwriting the first loaded sector is correct. However, in this instance, the OP would probably use something closer to this, assuming that ES and BX are not clobbered by the BIOS:
@stevewoods1986: In my own VERBUM boot sector demonstrator, I use an approach similar to the one onlyonemac used (as shown above), but I also used some NASM assembler macros to ease the process of calling some routines (though not the one for reading from disk), EQUates to give names to important constants, and memory variables to hold the values rather than hard-coding them.
equates:
macros:
data section (which I put below the code):
disk reset and read functions
The part of the actual loader that calls this is:
The point is that just because you are using assembly doesn't mean you have to throw good coding practices out the window. In this case, I probably should re-write this to use parameters for those arguments, as onlyonemac did, rather than hard-coding in the addresses, but one thing at a time.
You're point about it overwriting the first loaded sector is correct. However, in this instance, the OP would probably use something closer to this, assuming that ES and BX are not clobbered by the BIOS:
Code: Select all
add bx, 0x10 ; advance the load location by 512 bytes
int 0x13
equates:
Code: Select all
;;constants
;
%define boot_base 0x0000 ; the segment:offset pair for the
%define boot_offset 0x7C00 ; boot code entrypoint
stage2_base equ 0x1000 ; the segment:offset to load
stage2_offset equ 0x0000 ; the second stage into
stack_seg equ 0x9000
stack_top equ 0xFFFC
VBIOS equ 0x10 ; BIOS interrupt vector for video services
GOTO_XY equ 0x02 ; VBIOS routine - go to the given x, y coordinates
block_write equ 0x09 ; VBIOS routine - write a fixed number of times to the screen
ttype equ 0x0E ; VBIOS routine - print character, teletype mode
DBIOS equ 0x13 ; BIOS interrupt vector for disk services
disk_reset equ 0x00 ; disk reset service
disk_read equ 0x02 ; disk read service
; BIOS error codes
reset_failure equ 0x01 ; error code returned on disk reset failure
read_failure equ 0x02 ; error code returned on disk read failure
; operational constants
tries equ 0x03 ; number of times to attempt to access the FDD
Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; macros
;
%define zero(x) xor x, x
%macro write 1
mov si, %1
call printstr
%endmacro
Code: Select all
[section data]
loading db 'Loading stage two... ', NULL
done db 'done.', CR, LF, NULL
snd_stage db 'Second stage loaded, proceeding to switch context.', CR, LF, NULL
returned db 'Control returned to first stage, ', NULL
reset_failed db 'Could not reset drive,', NULL
read_failed db 'Could not read second stage, ', NULL
exit db ' system halted.', NULL
bootdrv resb 1 ; byte reserved for boot drive ID number
; DBIOS arguments, values given are defaults
cyl db 0 ; cylinder to read from
head db 0 ; head to read from
startsector db 2 ; sector to start reading at
numsectors db 1 ; number of sectors to read
disk reset and read functions
Code: Select all
; reset_disk
reset_disk:
mov dl, [bootdrv]
mov ah, disk_reset
int DBIOS
ret
; read_disk
read_disk:
mov cx, tries ; set count of attempts for disk reads
.try_read:
push cx
mov cx, tries ; set count of attempts to reset disk
.try_reset:
call reset_disk
jnc short .read
loop .try_reset ; if the reset fails, try up to three times
mov ax, reset_failure ; if all three fail, set an error code and return
pop cx ; make sure that the stack is correctly aligned
jmp short .end_fail
.read:
mov ax, stage2_base
mov es, ax
mov dl, [bootdrv]
mov ch, [cyl] ; cylinder
mov dh, [head] ; head
mov cl, [startsector] ; first sector
mov al, [numsectors] ; number of sectors to load
mov ah, disk_read
mov bx, stage2_offset
int DBIOS
jnc short .end_success
pop cx
loop .try_read
mov ax, read_failure ; if attempts to read the disk fail, report error code
jmp short .end_fail
.end_success:
pop cx ; make sure that the stack is correctly aligned
zero(ax)
.end_fail:
ret
Code: Select all
mov [bootdrv], dl ; save boot drive info for later use
; read in the data from disk and load it to ES:BX (already initialized)
write loading
call read_disk
cmp ax, reset_failure
jne good_reset
write reset_failed
jmp short shutdown
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
-
- Member
- Posts: 80
- Joined: Wed Aug 09, 2017 7:37 am
Re: How do I load my sector with if it's more than 512 bytes
What? So it's not 0x7c00? I don't need to jump to DS:BX?neon wrote:Hello,
The provided code loads to 0x7c000 and 0x7e000 not 0x7c00. However, I suspect this might have not been done intentionally; it might be a good idea for the original poster to review segmentation.
- How are you copying the boot record to the disk image?
- What happens if you load it to 0x7e0:0 and 0x800:0? You should not need a jump since the sectors would be loaded in consecutive memory.
- Where is the stack?
I don't know where the stack is... Is it at 0x7c00?
Do I have to do mov sp, 0x7c00?
Am I an idiot?