Is there a way through code to know a hard disk location?

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.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Re: Is there a way through code to know a hard disk location

Post by Brynet-Inc »

I don't know what this thread is about, I just like reading my own posts.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
Braceq
Posts: 9
Joined: Wed Apr 04, 2012 10:13 pm

Re: Is there a way through code to know a hard disk location

Post by Braceq »

I am having trouble accesing the forums, don't know why.
berkus wrote:Assume shall you not. Documentation read you must.
Yeah berkus, I already read about it before writing that :P (been more than 1 year reading int 13h docs and failing like an idiot) and I clearly read that carry flag 0 means success. However, I'm not experienced on this so something might have happened in between and that's why I was hoping I was doing it right. In short I'm not confident in what I'm looking on the screen, hence I need more proves to really really make sure everything is working smoothly. I swear that if I ever finish making my boot loader I'm going to make a working tutorial on how to read from a hard disk, not floppy and explanation of line after line (and of course link to all the documentation I've used including OSDev Wiki, even though I started a couple of days ago reading OSDev Wiki for the first time. I didn't even know this place existed until someone from another forum led me here.)

Here is the code that right now is giving me a carry flag of 0 right after executing INT 13H:
EDIT: Hence, success on reading from hard disk.

Code: Select all

#make_boot#

org 7c00h      ; set location counter.

MOV AH, 0      ;reset disk
INT 13H

MOV AL, 1      
MOV CL, 1

;Following 4 lines were copied from TrueCrypt Bootloader..
    MOV CH, 0           ; Cylinder
	MOV DH, 0       ; Head
			     ; DL = drive number passed from BIOS
	MOV AH, 2
	INT 13h
;End of copied code

JNC success

error:
LEA SI, errmsg
MOV AH, 0Eh
show_errmsg:
MOV AL, [SI]
CMP AL, 0
JZ exit
INT 10H
INC SI
JMP show_errmsg

success:
LEA SI, succmsg
MOV AH, 0Eh
show_succmsg:
MOV AL, [SI]
CMP AL, 0
JZ exit
INT 10H
INC SI
JMP show_succmsg

exit:
MOV AH, 0
INT 16H        ;wait for any key
INT 19h        ; reboot

errmsg DB 'Could not read hard disk.'
succmsg DB 'A disk read has been successful since carriage flag is 0.'
So it appears to be working since I'm getting the succmsg. I'll continue now with the info DavidCooper has pointed out and see if I can finally make sure I'm reading the hard disk correctly before continuing any further.
Merlin wrote:and DL gives you the drive that you booted from, why is that not helpfull?
My bad, didn't know it was like that. I thought it was a necessity to specify the storage device, not that it was passed by BIOS, but my code above shows that it is indeed passed by BIOS.
DavidCooper wrote:I can't not admire someone who hasn't given up after so much lack of success. It isn't immediately clear what you're trying to do, so can you clarify it so that everyone can see exactly what's what. Are you trying to boot this code from a USB flash drive in order to try to read from the internal hard drive of the computer and then to print its MBR to the screen?
What you just mentioned is exactly what I'm trying to do:wink: . It's a test to see if I'm on the right path. If it works I'll continue with the rest of the boot loader to eventually install it on the disk.
DavidCooper wrote:Are you sure you want to work with the value in DS? How do you know what it is? Set up your own segments so that you know exactly what's in them.
You are right, now that you mention it I have not idea what will be on the Data Segment when executing INT 13H.
DavidCooper wrote:Are you sure you want cylinder 1 rather than 0, and is there such a thing as sector 0 when using Int 13h with AH=2h?
I read somewhere that CH cannot be 0, but can't remember where. I've read so many variants of INT 13H that in that moment that was what the documentation told me. There are too many different documents on INT 13H. Ones add detail others omit details and I believe that because of that one say one thing for a register and the other says another thing. Or it could just be that I was interpreting wrong after reading so much.
DavidCooper wrote:I've never worked out what LEA is for, but I'm hoping it does the same as a MOV here. Even so,...
In that piece of code LEA stores the address of buffer into SI. On the other hand, MOV would try to store the value inside Buffer into SI. Don't really know if the compiler will allow me to perform a MOV between Buffer and SI.

I will try what you are telling me
DavidCooper wrote:It would be better just to line up on an address directly for the data from disk to be written to and to load registers with the same direct address to access them, using numbers - stick it somewhere well out of the way such as at the 128K point (and set up a stack at 7C00 while you're at it).
I am going to try that. Thanks for mentioning it.
DavidCooper wrote:How do you know there's going to be a 0 at the end of the data? The memory could have anything in it, so you'd need to write a zero after the loaded sector first. Worse though, it will stop printing at the first 0 in the data that it reaches, so it's completely the wrong approach. Set up a count of 512 and stop when that count runs out.
DavidCooper wrote:Set ES to b800h and DI to 0, then move BL into AL and set AH to 12 (red colour) and post it to the screen with STOSW, then move BH into AL and use STOSW again. For a clearer view of the content of BX, convert it to hex first and print four bytes to the screen instead, but do it the simpler way first even though it's harder to interpret the result as it will make sure you've got the hang of printing directly to the screen.
DavidCooper wrote:Your best bet is to look at the content of DL right at the start and store it - if it isn't 80h, the hard drive will almost certainly be 80h, but if DL is already 80h (I don't know if that ever happens), I'm guessing that you'd then find the hard drive at 81h, and if that failed you could then rewrite the code to try other values.
Thanks for all those, I'll put them to work and see what happens.
DavidCooper wrote:Edit:-

You also need the boot sig in the last two bytes of your boot sector, and that's AA55h.
I'm not so sure. To stay on the safe side I've been doing that, but I read on the OSDev Wiki that such signature is no longer required on modern BIOS anymore.

Thank you all, I'll continue working then.
User avatar
brain
Member
Member
Posts: 234
Joined: Thu Nov 05, 2009 5:04 pm
Location: UK
Contact:

Re: Is there a way through code to know a hard disk location

Post by brain »

Tl;Dr... I see a compromise here: read all relevant docs and specs, and take them with a pinch of salt as they are never 100% accurate due to addenums, erattas and breakages. this method has always worked for me...
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Is there a way through code to know a hard disk location

Post by DavidCooper »

Braceq wrote:Here is the code that right now is giving me a carry flag of 0 right after executing INT 13H:
EDIT: Hence, success on reading from hard disk.
Success of a kind perhaps, but not reading from the hard disk - because you aren't changing DL any more, you're now reading from the drive you've just booted from.

Code: Select all

MOV AH, 0      ;reset disk
INT 13H
Harmless. If the flash drive's acting as a floppy disk (which it will be if you've put your code on top of its MBR) and DL contains 0 (which it may do), then this'll reset the flash drive. If DL contains a value higher than 7Fh, it'll reset the hard disk as well.
MOV AL, 1
MOV CL, 1

;Following 4 lines were copied from TrueCrypt Bootloader..
MOV CH, 0 ; Cylinder
MOV DH, 0 ; Head
; DL = drive number passed from BIOS
MOV AH, 2
INT 13h
;End of copied code
So you've just left it to chance where that sector gets loaded instead of going to the little trouble of loading ES:BX with a destination. You shouldn't need to copy bits of this from a tutorial - you should be working out for yourself which values to put in which registers by using reliable information like this: http://en.wikipedia.org/wiki/INT_13H, or for a little more detail http://www.cs.cmu.edu/~ralf/files.html (Part A, second of the files called INTERRUP).
You also need the boot sig in the last two bytes of your boot sector, and that's AA55h.
I'm not so sure. To stay on the safe side I've been doing that, but I read on the OSDev Wiki that such signature is no longer required on modern BIOS anymore.
Don't leave it out - I had to start using it in order to get my OS to boot on modern hardware.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re: Is there a way through code to know a hard disk location

Post by bubach »

Braceq wrote:In that piece of code LEA stores the address of buffer into SI. On the other hand, MOV would try to store the value inside Buffer into SI. Don't really know if the compiler will allow me to perform a MOV between Buffer and SI.
MOV SI, message takes the address and puts in SI while MOV SI, [message] takes contents. LEA has other useful properties as can be seen here, but not necessary for the simple task of putting a string address in SI.
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
Braceq
Posts: 9
Joined: Wed Apr 04, 2012 10:13 pm

Re: Is there a way through code to know a hard disk location

Post by Braceq »

Out of topic: Am I banned from this forum? I can't access it with my real IP. I get a Server Not Found error?

On topic:
bubach wrote:MOV SI, message takes the address and puts in SI while MOV SI, [message] takes contents. LEA has other useful properties as can be seen here, but not necessary for the simple task of putting a string address in SI.
Hehe. Well, I don't know another way of printing a string in real mode, I mean, I don't think I can use int 21h with function 02h in real mode. I also have no idea where I learned using lea from. Maybe some old tutorial...
DavidCooper wrote:Success of a kind perhaps, but not reading from the hard disk - because you aren't changing DL any more, you're now reading from the drive you've just booted from.
I sort of suspected that, but I just manually entered

Code: Select all

MOV DL, 0x80
and it worked out, I got a 0 carry flag. That might mean I was reading from the hard disk, but won't know till I print the read bytes out :wink: .
DavidCooper wrote:So you've just left it to chance where that sector gets loaded instead of going to the little trouble of loading ES:BX with a destination.
No, no no no, please don't take me wrong. This was just a carry flag test since I couldn't manage to print read bytes into screen. Now I'm going to print the read bytes into the screen to finally make sure everything is right, and for that I will have to do just what you said. Load an address location into ES:BX so the read bytes go there and I can later access them and print them on the screen...... Just, I don't know how to do that. Don't worry, something will come up. Maybe I'll use SI and DS to set it up, I don't know, when I get to it I'll see. Don't worry I won't take another year figuring that out. Haha!

I know someone here might think, "If you don't know how to do such a basic operation, why are you even here, no wonder you have taken so long just to make a boot loader". Well, I don't care, I'm learning and having fun. Plus, what seems clear to you experience programmers is not so clear to me.
DavidCooper wrote:Don't leave it out - I had to start using it in order to get my OS to boot on modern hardware.
Ok.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re: Is there a way through code to know a hard disk location

Post by bubach »

Braceq wrote:Hehe. Well, I don't know another way of printing a string in real mode, I mean, I don't think I can use int 21h with function 02h in real mode. I also have no idea where I learned using lea from. Maybe some old tutorial...
Did you read my post? What does int 21h or how you print the string got to do with anything? I said LEA is pointless here, you can switch it to a MOV - because it does the same thing.
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
Braceq
Posts: 9
Joined: Wed Apr 04, 2012 10:13 pm

Re: Is there a way through code to know a hard disk location

Post by Braceq »

bubach wrote:
Braceq wrote:Hehe. Well, I don't know another way of printing a string in real mode, I mean, I don't think I can use int 21h with function 02h in real mode. I also have no idea where I learned using lea from. Maybe some old tutorial...
Did you read my post? What does int 21h or how you print the string got to do with anything? I said LEA is pointless here, you can switch it to a MOV - because it does the same thing.
Sorry. But that doesn't compile anyway, if I change LEA for MOV.

Code: Select all

LEA SI, errmsg
For

Code: Select all

MOV SI, errmsg
It says: "operands does not match 16 bit register and 8 bit address".

Only way I found to make it compile is to make

Code: Select all

MOV SI, w.errmsg
And even though, it doesn't work correctly. I'll stick to LEA, it doesn't hurt after all.
berkus wrote:
Braceq wrote:Load an address location into ES:BX so the read bytes go there and I can later access them and print them on the screen...... Just, I don't know how to do that.

Code: Select all

mov bx, 0xb800
mov es, bx
xor bx, bx
Should do it, you won't even need a print routine :P
I wanted to figure that out, but thanks.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re: Is there a way through code to know a hard disk location

Post by bubach »

Hi, that is odd. Very odd. I would try to figure out why, but don't have the time to check your code right now. But I did notice one rather big issue in your print code. You do a CMP for zero to check when the string is ended, but you don't include a zero at the end of the string. It should look like this: errormsg db "any text here", 0
Otherwise it doen't know when to stop printing, and could go and an print out half your RAM...
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
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: Is there a way through code to know a hard disk location

Post by Combuster »

the use of LEA reg, name instead of LEA reg, [name] suggests you're at least using an exotic assembler for our standards, which means that the result of any instruction could be different from what we expect and easily lead to us fixing your code to work for everyone except you.

Since you also seem to lack the knowledge of how your assembler actually works, you'd probably be better off ditching it and use yasm or nasm instead so we're not debugging the problem between the keyboard and chair.
"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 ]
Braceq
Posts: 9
Joined: Wed Apr 04, 2012 10:13 pm

Re: Is there a way through code to know a hard disk location

Post by Braceq »

Oh men. I'm officially at the beginning then. I was using the compiler every noob uses, emu8086.

Well, I just compiled more tries with NASM, but none of them are working. It's just loading for a couple of seconds and continuing with the boot loader at hard disk without even waiting for any key. I get no message whatsoever.

I have to go back to the university tomorrow so I'll post back when I get the carry flag test (that is get a 0 right after executing INT 13H) working again, but this time with NASM. I'm not going to ask for help anymore (for the moment), but I'll leave the non working code I have right now compiled with NASM for if anyone might spot something if they want. To think that with the code berkus gave me I was getting a bunch of characters printed on the screen that wasn't the MBR, but I was getting something at least. I was so close, now I'm at the beginning again. #-o

Code: Select all

[BITS 16]	;This is 16 bits code
[ORG 0x7C00]	;We will begin executing code at this address



MOV AH, 0
INT 13H

MOV AL, 1        ;Read 1 Sector
MOV AL, 1        ;Read sector #1 


;Code berkus wrote that will put read sectors into 0xb800 and automatically print it to the screen
MOV BX, 0xb800
MOV ES, BX
XOR BX, BX
;End of code

;Following 4 lines were copied from TrueCrypt Bootloader..
    MOV CH, 0           ; Cylinder
    MOV DH, 0       ; Head
    MOV DL, 0x80    ; DL = drive number passed from BIOS
    MOV AH, 2
    INT 13h

;End of copied code



JNC exit

error:
MOV SI, errmsg
MOV AH, 0Eh
show_errmsg:
MOV AL, [SI]
CMP AL, 0
JZ exit
INT 10H
INC SI
JMP show_errmsg

success:
MOV SI, succmsg
MOV AH, 0Eh
show_succmsg:
MOV AL, [SI]
CMP AL, 0
JZ exit
INT 10H
INC SI
JMP show_succmsg

exit:
MOV AH, 0
INT 16H        ;wait for any key
INT 19h        ; reboot

errmsg DB 'Could not read hard disk.', 0
succmsg DB 'A disk read has been succesful since carriage flag is 0.', 0

TIMES 510 - ($ - $$) db 0	;fill the rest of sector with 0
DW 0xAA55                       ;Signature
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Is there a way through code to know a hard disk location

Post by Brendan »

Hi,
Braceq wrote:Well, I just compiled more tries with NASM, but none of them are working.
This is like watching a drunk monkey try to win at chess - it's funny for the first 5 minutes, until you realise how excruciatingly depressing it is.

Here (for NASM):

Code: Select all

    bits 16
    org 0x7C00

    jmp start               ;Needed for some ancient Compaq machines

;Space for BPB here 

start:
    xor ax,ax
    mov ds,ax
    mov es,ax
    cli                     ;Needed for 8086
    mov ss,ax
    mov sp,0x7C00           ;Put stack just below this code
    sti
    mov [diskNumber],dl     ;Save disk number for later

    mov ax,0x0003
    int 0x10                ;Make sure video mode is sane

    mov si,helloString
    call printString        ;Say "hello"

    mov cx,0x0001           ;cx = first sector of track 0
    xor dh,dh               ;dh = head 0
    mov bx,0x7E00           ;es:bx = address of byte after boot loader (ES already set from above)
    call loadSector         ;Load the sector

    mov si,loadedString
    call printString        ;Say it loaded

    mov si,0x7E00           ;ds:si = address of first byte of loaded sector
    mov cx,8                ;cx = number of lines to dump to screen (64 bytes per line * 8 lines = 512 bytes)
.nextLine:
    call printLine
    loop .nextLine

.die:
    hlt                     ;Lock up forever
    jmp .die


;Routine to print a line of ASCII characters from memory
;
;Input
; DS:SI = address of memory to dump to screen
;
;Input
; DS:SI = address of byte after memory dumped to screen

printLine:
    push cx
    mov cx,64               ;Number of characters per line
    cld
.next:
    lodsb
    cmp al,' '              ;Can the byte be displayed as ACSII?
    jbe .badChar            ; no, too low or space, use '.' instead
    cmp al,0x7F             ;Can the byte be displayed as ACSII?
    jb .doChar              ; yes
                            ; no, too high or delete, use '.' instead
.badChar:
    mov al,'.'
.doChar:
    mov ah,0x0E
    int 0x10
    loop .next
.done:
    mov ax,0x0E0A           ;Newline
    int 0x10
    mov ax,0x0E0D           ;Carriage return
    int 0x10

    pop cx
    ret


;Routine to print the ASCIIZ string
;
;Input
; DS:SI = address of ASCIIZ string

printString:
    cld
    lodsb
    test al,al
    je .done
.next:
    mov ah,0x0E
    int 0x10
    lodsb
    test al,al
    jne .next
.done:
    ret

;Routine to load one sector with retries
;
;Input
; CH = low eight bits of cylinder number
; CL = sector number 1-63 (bits 0-5), high two bits of cylinder (bits 6-7, hard disk only)
; DH = head number
; ES:BX = address to load the sector

loadSector:
    mov byte [retries],0
.retry:
    pusha
    mov ax,0x0201           ;ah = read sectors function, al = 1 sector
    mov dl,[diskNumber]
    int 0x13
    jnc .done
    inc byte [retries]
    cmp byte [retries],5    ;Max. retries
    jae .failed
    popa                    ;Reload original registers
    test byte [retries],1   ;Is "number of attempts so far" even?
    je .retry               ; Yes, don't reset disk system

    pusha
    mov ax,0x00             ;ah = reset disk subsystem function
    mov dl,[diskNumber]
    int 0x13
    popa
    jmp .retry

.failed:
    mov si,failedString
    call printString        ;Tell the user it failed
    popa
.die:
    hlt                     ;Lock up forever
    jmp .die

.done:
    popa
    ret


diskNumber:   db 0
retries:      db 0

helloString:  db "Hello",10,13,0
failedString: db "Failed to load sector",10,13,0
loadedString: db "Sector loaded OK",10,13,0

    times 510 - ($ - $$) db 0     ;Fill the rest of sector with 0
    dw 0xAA55                     ;"bootable" signature
Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re: Is there a way through code to know a hard disk location

Post by bubach »

emu8086? every noob? seriously, never heard of it... anyway, fasm is also a very good alternative that usually has support for the newest opcodes way before nasm.
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
rdos
Member
Member
Posts: 3306
Joined: Wed Oct 01, 2008 1:55 pm

Re: Is there a way through code to know a hard disk location

Post by rdos »

Seems like the assembler the OP uses use MASM syntax. If that is so, there is a need to use the OFFSET operator in order to load an address into a register.

However, if this is the case, many other things written for NASM will simply fail. The only way to guard against this is to use segment overrides with all memory accesses, and OFFSET operator for all loads of addresses. That is how I always write assembler-code.
User avatar
brain
Member
Member
Posts: 234
Joined: Thu Nov 05, 2009 5:04 pm
Location: UK
Contact:

Re: Is there a way through code to know a hard disk location

Post by brain »

Emu8086 is an educational, closed source commercial emulator, assembler and disassembler all in one. you aren't also running your code within emu8086 are you?
Post Reply