Is there a way through code to know a hard disk location?
- Brynet-Inc
- 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
I don't know what this thread is about, I just like reading my own posts.
Re: Is there a way through code to know a hard disk location
I am having trouble accesing the forums, don't know why.
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.
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.
I will try what you are telling me
Thank you all, I'll continue working then.
Yeah berkus, I already read about it before writing that (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.)berkus wrote:Assume shall you not. Documentation read you must.
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.'
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.Merlin wrote:and DL gives you the drive that you booted from, why is that not helpfull?
What you just mentioned is exactly what I'm trying to do . 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: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?
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 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.
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: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?
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.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,...
I will try what you are telling me
I am going to try that. Thanks for mentioning it.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).
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.
Thanks for all those, I'll put them to work and see what happens.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.
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.DavidCooper wrote:Edit:-
You also need the boot sig in the last two bytes of your boot sector, and that's AA55h.
Thank you all, I'll continue working then.
Re: Is there a way through code to know a hard disk location
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...
- DavidCooper
- 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
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.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.
Code: Select all
MOV AH, 0 ;reset disk
INT 13H
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).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
Don't leave it out - I had to start using it in order to get my OS to boot on modern hardware.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.You also need the boot sig in the last two bytes of your boot sector, and that's AA55h.
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
MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Re: Is there a way through code to know a hard disk location
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.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.
Re: Is there a way through code to know a hard disk location
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:
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 .
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.
On topic:
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...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.
I sort of suspected that, but I just manually enteredDavidCooper 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.
Code: Select all
MOV DL, 0x80
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!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.
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.
Ok.DavidCooper wrote:Don't leave it out - I had to start using it in order to get my OS to boot on modern hardware.
Re: Is there a way through code to know a hard disk location
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.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...
Re: Is there a way through code to know a hard disk location
Sorry. But that doesn't compile anyway, if I change LEA for MOV.bubach wrote: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.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...
Code: Select all
LEA SI, errmsg
Code: Select all
MOV SI, errmsg
Only way I found to make it compile is to make
Code: Select all
MOV SI, w.errmsg
I wanted to figure that out, but thanks.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.Should do it, you won't even need a print routineCode: Select all
mov bx, 0xb800 mov es, bx xor bx, bx
Re: Is there a way through code to know a hard disk location
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...
Otherwise it doen't know when to stop printing, and could go and an print out half your RAM...
- Combuster
- 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
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.
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.
Re: Is there a way through code to know a hard disk location
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.
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.
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
Re: Is there a way through code to know a hard disk location
Hi,
Here (for NASM):
Cheers,
Brendan
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.Braceq wrote:Well, I just compiled more tries with NASM, but none of them are working.
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
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.
Re: Is there a way through code to know a hard disk location
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.
Re: Is there a way through code to know a hard disk location
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.
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.
Re: Is there a way through code to know a hard disk location
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?