BIOS Floppy Access

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
CROM
Posts: 6
Joined: Wed Jan 27, 2010 1:57 am

BIOS Floppy Access

Post by CROM »

Greetings,

I have been trying to get my boot loader to read data off of a floppy disk in real mode with INT 0x13. When I check the status of the floppy drive using INT 0x13, it always (seemingly) returns something other than 0, so there's an issue.
I'm not very experienced with assembly, so this might just be a case of a trivial syntax error... Unfortunately, I've been working on this for a long time.

Code: Select all

;Intel syntax

mov ah, 0
mov dl, 0
INT 0x13 ; reset floppy drive first...

mov ah, 0x01
INT 0x13  ; check drive status

cmp al, 0 ; this never seems to be true
Also, on another note, does enabling the A20 address line even matter if the intention is to go into protected mode as soon as possible? From my understanding, A20 is useful for addressing more memory in real mode, but doesn't it get automatically enabled, along with the other 12 or so additional lines, when the machine enters protected mode? From what I've been able to determine, enabling A20 specifically is only worth doing if the system is to perform some heavier work in real mode before switching to protected. I've found the issue confusing, only because there is a significant amount of emphasis put on enabling that address line in the material I've read. Perhaps I've just been reading old material? Please correct me if I'm wrong on this, I would appreciate it very much.

Thanks in advance for any ideas.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: BIOS Floppy Access

Post by AJ »

Hi,

What's the error? Is the value always the same or does it vary? Is DL valid (what value is passed in DL from the BIOS at boot time)? Do you even need to be using function 0x01, when the reset operation should return a status value in AH? What is the value of CF after each operation?

Sorry to pose you all these questions, instead of giving an answer! If you can check all these points and the code still does not work, it may be useful to see more code to put your snippet in to context.

As for A20, yes, you do need to enable it. If you do not, the address line will still be disabled when you enter protected mode and you will only be able to access every other megabyte of memory.

Cheers,
Adam
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: BIOS Floppy Access

Post by Combuster »

You can begin by looking up the error code here

What you should at least take into account is that some floppy drives fail to work on the first few tries, so in some cases you will have to try again several times until it does work.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: BIOS Floppy Access

Post by xenos »

IIRC, the A20 line is disabled by mainboard hardware at bootup, not by the CPU. If you enter protected mode, you only change the state of the CPU, but the A20 line is still disabled by mainboard hardware. That's why you have to enable it separately, sending some bytes via port I/O to the mainboard hardware.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: BIOS Floppy Access

Post by jal »

There are a few misconceptions in your post. I'll deal with them one at a time.
CROM wrote:From my understanding, A20 is useful for addressing more memory in real mode
The A20 line was introduced on the AT (sporting a 80286) to have it emulate the 8086's behaviour in real mode. If it is not set, memory access above 1MB (in real mode) will wrap around to 0, just like on the PC/XT. If it is set, memory access above 1MB will not wrap around, making it possible to reach address 10FFEF (bij using segment FFFF and offset FFFF), i.e. a total of 64KB above 1MB.
but doesn't it get automatically enabled, along with the other 12 or so additional lines, when the machine enters protected mode?
No, since it is a chipset feature: the CPU is blissfully unaware of it. The other address lines are also "enabled" in real mode, it is just that you cannot get to them by using real mode addressing (at least, not until the 80386 and the "unreal" mode trick).

Hope this helps.


JAL
CROM
Posts: 6
Joined: Wed Jan 27, 2010 1:57 am

Re: BIOS Floppy Access

Post by CROM »

Thanks a lot for the information on A20.
Combuster wrote:You can begin by looking up the error code here

What you should at least take into account is that some floppy drives fail to work on the first few tries, so in some cases you will have to try again several times until it does work.
I thought of that, and at one point I had it looping to check the status over and over again, but it always returned something other than 0.
AJ wrote:Hi,
What's the error? Is the value always the same or does it vary? Is DL valid (what value is passed in DL from the BIOS at boot time)? Do you even need to be using function 0x01, when the reset operation should return a status value in AH? What is the value of CF after each operation?
For the record, CF is not set after either operation.
DL is set to 0, which is apparently the identifier for the first floppy drive. As far as I know, that's fine.
In terms of testing the value, I was writing out a table of tests to do so, but it wasn't the most efficient way of doing so. It was like this:

Code: Select all

cmp al, 0
je code_00

cmp al, 0x01
je code_01

; This repeats for every possible error code, and jumps to...

code_00:
	mov byte[0x0B0000], 0x41
	jmp $
code_01:
	mov byte[0x0B0000], 0x42
	jmp $

; And so on.
The idea was that for each different error code, a different character would be put into the video memory, and then I could look up which error code was associated with that character. Can anyone suggest a faster way (if possible) of doing this? I haven't finished writing this out, due to the multitude of possible error codes. There must be a better way...

Just in case anyone suggests it, the issue isn't with a damaged floppy drive, because I have identical results whether I try this in QEMU or with a real, physical machine.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: BIOS Floppy Access

Post by Combuster »

If CF is clear, there was no error, and thus there is no error code to report. The RBIL is rather vague about AH being set or to assume zero in this case, so you best ignore it. In any case, CF=clear is the equivalent of no error.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: BIOS Floppy Access

Post by AJ »

CROM wrote:

Code: Select all

cmp al, 0
je code_00

cmp al, 0x01
je code_01

; This repeats for every possible error code, and jumps to...

code_00:
	mov byte[0x0B0000], 0x41
	jmp $
code_01:
	mov byte[0x0B0000], 0x42
	jmp $

; And so on.

Code: Select all

; <- disk operation here
add al, 0x41
mov byte[0xb8000], al
jmp $
:)

Cheers,
Adam
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: BIOS Floppy Access

Post by Owen »

Altetnatively, if you need every possible value...

Code: Select all

mov ah, al
mov bl, al
shr bl, 6
shr ah, 3
and al, 7
and ah, 7
add al, 0x30
add ah, 0x30
add bl, 0x30
mov byte[0xb8000], bl
mov byte[0xb8002], ah
mov byte[0xb8004], al
though admittedly that's somewhat longer ;)
CROM
Posts: 6
Joined: Wed Jan 27, 2010 1:57 am

Re: BIOS Floppy Access

Post by CROM »

Thanks a lot everyone. I'll take all of this into account, and see if I can get it working.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: BIOS Floppy Access

Post by xenos »

Owen wrote:Altetnatively, if you need every possible value...
...and you are familiar with octal numbers ;)
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
CROM
Posts: 6
Joined: Wed Jan 27, 2010 1:57 am

Re: BIOS Floppy Access

Post by CROM »

I still have not had any success in reading data from the floppy drive. CF is not set, yet no data appears in the buffer that I am intending to deposit it in (using QEMU's memory dump feature and I hex editor, I verified this). Here is the code that is used to attempt a read from floppy:

Code: Select all

reset_floppy:
mov ah, 0
mov dl, 0
INT 0x13

read_floppy:
mov ah, 0x02
mov al, 1 ; read one sector
mov ch, 00000001b ; cylinder #1? I've started counting at 0 for these three following parameters, same result
mov cl, 00000100b  ; sector #1? first 6 bits are for sector #...
mov dh, 1; head #1? 
mov dl, 0 ; 1st floppy drive
mov bx, 0x007E ; bx is 7E00, the place I want the data buffer to be
xor ax, ax
mov es, ax ; es should be 0, meaning a buffer 0x0000:0x7E00

jc reset_floppy
My intention is to load my boot loader from the first sector of the floppy disk to absolute address 0x7E00. Not for any practical purpose, it's just a test. As I mentioned above, I've tested this with both 0 specifying the first sector/cylinder/head and 1, with the same result. Using this code, nothing is stored at the buffer address, the memory is still zeroed (as QEMU initializes it). I imagine that my problem has something to do with specifying the ES:BX address of the buffer, because I'm still not sure how exactly real mode segmentation works.

For reference, I used this page: http://www.ctyme.com/intr/rb-0607.htm
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: BIOS Floppy Access

Post by xenos »

It's been a while since I used the BIOS for disk access... However, I just looked up my old docs:
entry AH 02h
AL number of sectors to read
BX address of buffer (ES=segment)
CH track (cylinder) number (0-39 or 0-79 for floppies)
(for hard disk, bits 8,9 in high bits of CL)
CL sector number (1 to 18, not value checked)
DH head number (0 or 1)
DL drive (0=A, 1=B, etc.) (bit 7=0) (drive 0-7)
00h-7Fh floppy disk
80h-FF0h hard disk
ES:BX address to store/fetch data (buffer to fill)
[0000:0078] dword pointer to diskette parameters

return CF clear successful
AL number of sectors transferred
set error
AH status (00h, 02h, 03h, 04h, 08h, 09h, 10h,
0Ah, 20h, 40h, 80h)
So if you want to read the first sector of your floppy, i.e. the boot sector, head (DH) should be 0, track (CH) should be 0, sector (CL) should be 1. You code reads some sector from the middle of the disk, which probably contains just nothing. Besides that, ES:BX in your code points to 0x0007e instead of 0x07e00. Try this:

Code: Select all

reset_floppy:
mov ah, 0
mov dl, 0
INT 0x13

read_floppy:
mov ah, 0x02
mov al, 1 ; read one sector
mov ch, 00000000b ; cylinder #0
mov cl, 00000001b  ; sector #1 - lower 6 bits are for sector #
mov dh, 0; head #0
mov dl, 0 ; 1st floppy drive
mov bx, 0x7E00 ; bx is 7E00, the place I want the data buffer to be
xor ax, ax
mov es, ax ; es should be 0, meaning a buffer 0x0000:0x7E00

jc reset_floppy
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
CROM
Posts: 6
Joined: Wed Jan 27, 2010 1:57 am

Re: BIOS Floppy Access

Post by CROM »

XenOS wrote: Besides that, ES:BX in your code points to 0x0007e instead of 0x07e00.
Oh, I thought the bytes had to be reversed in the instruction. I figured that a "mov bx, 0x7E00" would put 0x007E into BX. I'll just have to read into when to reverse the bytes and when not to.
XenOS wrote:

Code: Select all

read_floppy:
mov ah, 0x02
mov al, 1 ; read one sector
mov ch, 00000000b ; cylinder #0
mov cl, 00000001b  ; sector #1 - lower 6 bits are for sector #
mov dh, 0; head #0
mov dl, 0 ; 1st floppy drive
mov bx, 0x7E00 ; bx is 7E00, the place I want the data buffer to be
xor ax, ax
mov es, ax ; es should be 0, meaning a buffer 0x0000:0x7E00

jc reset_floppy
I tried this and, unfortunately, there still wasn't any data in the buffer.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: BIOS Floppy Access

Post by Gigasoft »

That's because first of all, you're not invoking int 13h, and you're also overwriting AX.

Try this instead (you're using NASM, right?):

read_floppy:
mov ax, 0x201
mov cx,1
xor dx,dx
mov bx, 0x7E00 ; bx is 7E00, the place I want the data buffer to be
push byte 0
pop es
int 0x13
jc reset_floppy
Post Reply