Bootcode - Extended Read Sector int 13, AH = 42

Started by Artoo, February 28, 2007, 02:58:35 AM

Previous topic - Next topic

Artoo

I have some bootcode that reads sectors off the hard disk. The problem that I am having is that reading a sector onto the stack doesnt work (int 31 returns AH as 0Ch), while reading the sector into a global varible seems ok.

Code:


;_____________________________________________________________________
;_____________________________________________________________________
;   IN: FS:DI = PTR to S_DriveStat
;        ES:BX = Data buffer
;        ECX = Sector
;        AL = Sectors to Read (AX for Extended Read)
;  OUT: AH return code: 0 = Success
ReadSector PROC
        LOCAL        dwRet        : DWORD
        LOCAL        sDAP        : S_DISK_ADDRESS_PACK
        LOCAL        TempBuffer[512]        : BYTE
        PUSHAD


        ;Override the ES:BX passed in with the address of the local TempBuffer
        LEA        BX, TempBuffer
        PUSH        SS
        POP         ES


ReadSector_Ex:


        MOV        sDAP.bySize,                        10h
        MOV        sDAP.byReserved,                0
        MOV        sDAP.wBufferOffset,                BX
        MOV        sDAP.wBufferSegment,                ES
        MOV        sDAP.wSectorCount,                AX
        MOV        sDAP.dwSectorNumberLo,                0
        MOV        sDAP.dwSectorNumberHi,                0

        LEA        SI, sDAP.bySize                                ; DS:SI = ptr to S_DISK_ADDRESS_PACK
        PUSH        DS
        PUSH        SS
        POP        DS

        MOV        EDX , FS:[DI.S_DriveStats.dwDiskNum]        ; Drive
        MOV        EAX, 4200h
        INT        13h
        MOV        dwRet, EAX
        POP        DS
        JNC        ReadSector_Ret                                ;Jmp if Successfull


;todo remove
        ;print the error code in AH
        PUSH        EAX
        CALL        AM_Print_NewLine
        CALL        AM_Print_NewLine
        POP        EAX
        CALL        AM_Print_EAX_16
        CALL        AM_Print_NewLine
        CALL        AM_Print_NewLine
        MOV        AH,0               ; wait for key
        INT                016h


ReadSector_Ret:
        POPAD

        MOV        EAX, dwRet
        XOR        AL,AL                ;EAX = 0 on success. Otherwise AH has error code.
        RET
ReadSector ENDP



Remove the the lines blow from the code above and everything works fine, that is because the ReadSector is called with ES:BX set to the address of variable is in code segment.


LOCAL        TempBuffer[512]        : BYTE        ;Override the ES:BX passed in with the address of the local TempBuffer


LEA        BX, TempBuffer
PUSH        SS
POP         ES


I really want to write to the stack and not the global variable.
Any ideas why a write to the stack doesnt work?

I have tried setting  ES:BX to the address of the stack before calling the proc, but its doesnt work either.
I have tried removing the lines descrbied above, and putting in a SUB SP,512  and  ADD SP,512 before and after the int 13h call, but this returns the same error code.

Your help is much appreciated!

japheth


Hi,

the code looks ok (if it is called with AX==1).

A wild guess is that your BIOS doesn't like the segment part of the buffer address to be 0000? IIRC at boot time SS might be 0. To verify you could add:

       mov cx, es
       inc cx
       mov es,cx
       sub bx,10h

before ReadSector_Ex.


MichaelW

The code looks OK to me too. If you set up a workable stack, preferably with SS=DS, and set the initial value of SP so the stack will not overwrite anything important, AFAICT the code should work OK.

eschew obfuscation

Artoo

thanks for your comments, but I am still stuck.

I am using Bochs to debug, and before the int 13 the registers are set to the following:

(0) [0x000088a8] 07e0:0aa8 (unk. ctxt): int 0x13                  ; cd13
<bochs:30> r
eax: 0x4200     16896
ecx: 0x0        0
edx: 0x80       128
ebx: 0xfd8f     64911
esp: 0xfd6d     64877
ebp: 0xffa3     65443
esi: 0xff8f     65423
edi: 0x512      1298
eip: 0xaa8
eflags 0x246
cs:  0x7e0
ss:  0x9000
ds:  0x9000
es:  0x9000
fs:  0x7e0
gs:  0x0


As you can see no segment register is set to 0. My code is at 07E0h and my stack is at 9000h.

and after the int 13:


00002020671i[BIOS ] int13_harddisk: function 42, error 01 !

eax: 0xa3ff0c00 -1543566336
ecx: 0x0        0
edx: 0x80       128
ebx: 0xfd8f     64911
esp: 0xfd6d     64877
ebp: 0xffa3     65443
esi: 0xff8f     65423
edi: 0x512      1298
eip: 0xaaa
eflags 0x247
cs:  0x7e0
ss:  0x9000
ds:  0x9000
es:  0x9000
fs:  0x7e0
gs:  0x0


Bochs says error 1. While the Result in AH is 0Ch

What do you guys think?

thanks again

sinsi

Are you trying to read more than 1 sector? I noticed that your buffer address is 9000:FD8F, so reading more than one sector would go past 9000:FFFF
Light travels faster than sound, that's why some people seem bright until you hear them.

Artoo

Nope just reading the one sector.  (I am reading partition info for hard drives).

japheth



ebx: 0xfd8f     64911
esp: 0xfd6d     64877
ebp: 0xffa3     65443
esi: 0xff8f     65423
edi: 0x512      1298
eip: 0xaa8
eflags 0x246
cs:  0x7e0
ss:  0x9000
ds:  0x9000
es:  0x9000
fs:  0x7e0


ss:sp == 9000:fd6d! Did you set these high values for the stack? It is not aligned, which is bad, but possibly worse is that Bochs's BIOS might have allocated the XBDA (extended BIOS data area) at segment FDC0, and you are now writing in this region.


Artoo

Thanks for the response japheth,

Yes I set the stack values.  Why are these bad? Why cant it be this high? Stack grows down so I gave it as much space as possible.

When you say aligned, do you mean dword aligned?  Why specifically does it need to be aligned? eg, the Int 13 needs it aligned?

How can I tell where Bochs XBDA is located?

Sorry..so many questions! :)



MichaelW

Interrupt 15h, AH=C1h should return the XBDA segment in ES, or return with the carry flag set in case of an error. On my test system it returns with ES=9FC0h.
eschew obfuscation

japheth


> is that Bochs's BIOS might have allocated the XBDA (extended BIOS data area) at segment FDC0

this was a typo, I meant 9FC0 of course  :red

> Why specifically does it need to be aligned?

No, it doesn't need to be, but it slows down the machine (possibly no problem on Bochs, since it is already very slow).

> Interrupt 15h, AH=C1h should return the XBDA segment in ES, or return with the carry flag set in case of an error.

Yes. Another method is to get the XBDA segment from 0040:000E

Artoo

The XBDA was the culprit!  I've modified my starting stack locations to 9000:CFFF and all is well!


thanks guys!!  :bg