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.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

I find it pretty hard to believe that so many forum pros never heard of MASM syntax. Is this yet another case of "we decide which design decisions you should make, and if you don't we will insult your competence?" :roll:
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

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
That code does not print anything. It just sets up the address to the usual area where the text-mode display can be manipulated. Also, it probably doesn't work with any non-NASM assembler, as they don't accept C-constants.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

A fair guess would also be that NASM code might not work with an emulator that expects it's own assembler to be used (and which uses MASM syntax).

And the presented NASM code is of little use since it won't compile in MASM-mode, and part of the things that do compile produce the wrong output (references to labels with no OFFSET or segment register override).
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 »

rdos wrote:I find it pretty hard to believe that so many forum pros never heard of MASM syntax. Is this yet another case of "we decide which design decisions you should make, and if you don't we will insult your competence?" :roll:
No. There wasn't anything unfamiliar with the syntax, just the assembler in question. Using an up to date assembler is sound advice no matter what syntax you want to use.
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
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,
bubach wrote:
rdos wrote:I find it pretty hard to believe that so many forum pros never heard of MASM syntax. Is this yet another case of "we decide which design decisions you should make, and if you don't we will insult your competence?" :roll:
No. There wasn't anything unfamiliar with the syntax, just the assembler in question. Using an up to date assembler is sound advice no matter what syntax you want to use.
Not using an assembler that generates completely different opcodes depending on context, can't be ported, and has potentially undesirable licence restrictions is sound advice too... ;)


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.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

bubach wrote:
rdos wrote:I find it pretty hard to believe that so many forum pros never heard of MASM syntax. Is this yet another case of "we decide which design decisions you should make, and if you don't we will insult your competence?" :roll:
No. There wasn't anything unfamiliar with the syntax, just the assembler in question. Using an up to date assembler is sound advice no matter what syntax you want to use.
But there was. All the constants used traditional MASM syntax, ending with "h", while all the constants in Brendans example use C syntax (0x prefix). Additionally, the OP claimed the assembler would complain that a byte cannot be loaded into a 16-bit register. This is because the assembler interpreted the instruction as mov si,ds:[some byte location] instead of mov si,OFFSET some label.

What assembler to use depends on many issues. For me it mostly depends on the issue of being compatible with my C/C++ compiler, and being compatible with my large code-base. That rules out anything except a MASM/TASM compatible syntax.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

Brendan wrote:Not using an assembler that generates completely different opcodes depending on context, can't be ported, and has potentially undesirable licence restrictions is sound advice too... ;)
I agree about undesirable licence restrictions, but there is at least one assembler that supports MASM syntax and that is free: WASM, the OpenWatcom assembler.

Additionally, last I checked, there where no safe way to convert code written for MASM/TASM syntax to NASM. This is because the difference of interpretation of statements without segment overrides or OFFSET operator. It might be possible to achieve if your code uses extensive segment overrides, and then the OFFSET operator is simply defined as a null, but then one missing case could break everything.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

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

Post by Solar »

rdos wrote:All the constants used traditional MASM syntax, ending with "h", while all the constants in Brendans example use C syntax (0x prefix).
Brendans code was clearly qualified as "for NASM". It is not up to Brendan to translate his example to the OP's assembler of choice.
Every good solution is obvious once you've found it.
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: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.
How could you tell that it wasn't the/an MBR? If you load the sector straight into screen memory like that, the first byte will display as a char, the 2nd as a colour value for that char, then the 3rd is another char, the 4th is a colour value for that char, etc. The only things that will show up as recognisable characters will be multicoloured strings like: "Ivldpriintbe" or "nai atto al" (where you're getting every other letter out of "Invalid partition table"); "Errlaigoeaigsse" or "rr odn prtn ytm" (Error loading operating system); "Msigoeaigsse" or "isn prtn ytm" (Missing operating system).
MOV AL, 1 ;Read 1 Sector
MOV AL, 1 ;Read sector #1
Why not do it three times just to make absolutely sure?
;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
Don't just copy code! Check the rules to make sure you aren't leaving anything out that might just turn out to be vital, such as the content of CL. You have no way of knowing which sector's being loaded without that. [Edit: ah, I've just realised why you loaded AL twice - one of them was your attempt to load CL, so it was actually just a single typing error and not two big mistakes.]

Don't just copy Brendan's code either - learn from it, but try to develop your own code, referring to his primarily to try to work out where yours is going wrong.
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
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 »

emu8086
Ok, somehow I almost expected that, and it also happens to be about the worst assembler alternative I could imagine. Heck, it couldn't even do proper shift instructions when I last tried it.

At least NASM comes with a nice manual as to what instructions and notations are available. You'll notice it's a lot more consistent, and at least you can find out what exactly an instruction does instead of guessing.
"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 ]
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

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

Post by rdos »

Combuster wrote:At least NASM comes with a nice manual as to what instructions and notations are available. You'll notice it's a lot more consistent, and at least you can find out what exactly an instruction does instead of guessing.
If NASM didn't allow direct referencing of labels, I think many more people would have ported their old code. They basically just redid the same problem that MS once did with their assumes. The x86 architecture does not define what a load of a label means. It is not a good idea to assume it means you load the address of the label (NASM way), nor is it a good idea to assume you load the value of the label, with implicit segment overrides (MASM way). It is perfectly possible to force users to indicate what they mean. That is what I call consistent and fault-tolerant.

Ideally, it should look like this: (a mix of NASM and MASM syntax)

Code: Select all

some_label  DB 45h

   mov si,OFFSET some_label
   mov al,cs:[si]
   mov al,cs:[some_label]
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 »

Well all syntax issues aside, when I first looked up emu8086 my first thought was that the OP was doing some form of project where he had to use that assembler. Guess not, though?
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 »

Hi again, I'm almost there. I don't know how many times I've said this, but anyway, I'm closer than before to finally print the MBR to the screen. The reason I left was because I was occupied with uni and I'm still but I wasn't making any progress with my code and it was taking too much time so put it on hold. After a few months I started again and I didn't wanted to just copy and paste someone else's code without understanding it so I didn't copy Brendan's code (thanks anyway Brendan) although in the end I ended up doing more or less copy and paste too from another person -.- I say more or less because I've modified it a bit but most of the instructions are the same. But in the literal meaning of the definition, yes that's what I did.

Since parts of the code weren't commented maybe because it might be something stupid that anyone should understand at first sight (except me), I pretty much flooded the code with comments and I wanted to show to you guys what I have until now. I've been studying how everything works in order to be able to comment pretty much everything. I know it's not a good practice in programming but I find assembly so exhaustive that I prefer to do it. If you care for looking at it and see that some of my comments are wrong then I would appreciate if you'd tell me so I can learn more. If you don't care, then no problem.

Well, here is the boot.asm code:

Code: Select all

%define store_location 0x1000
%define drive 0x80
%define code_sector_location 2 ;This is index 0 so we are actually pointing to sector 1.

bits 16
org 0x7c00

jmp start

start:

	mov ax, cs	;AX points to CS 0x7c0
	mov ds, ax	;DS points to 0x7c0
	mov es, ax	;ES contains what is on 0x7c0

	mov al, 03h	;Text mode 25x80
	mov ah, 0
	int 10h
	
	mov ax, store_location
	mov es, ax	;Point ES to store_location (top of our stack)
	mov cl, code_sector_location
	mov al, 3	;Number of sectors to read

	call read_sectors	;Load sectors and put them into RAM address of store_location

	jmp store_location:0000	;Far jump to offset 0000 to the segment in RAM where we have stored our program code after reading from it disk
	
	
read_sectors:
	mov bx, 0
	mov dl, drive
	mov dh, 0	;Head to read
	mov ch, 0	;Track to read
	mov ah, 2	;To read sectors
	int 0x13
	jc error_reading
	ret
	error_reading:
		mov si, error_msg
		call print
		mov ah, 0	;Wait for key press
		int 16h
		int 19h		;Reboot but leave memory to where is pointing

print:
	pusha	;Store all general-purpose registers on the stack
	mov bp, sp	;Allocates in stack program variables
	iterate:
		lodsb	;Loads 8bit byte address to work with strings
		or al, al	;Logic or to check if string already reached its end "0"
		jz done_writing
		mov ah, 0x0e	;To print character into screen
		mov bx, 0
		int 10h
		jmp iterate
	done_writing:
		mov sp, bp	;Get variables out of stack
		popa		;Retrieve all general-purpose registers of the stack with order LIFO ignoring SP
		ret

error_msg db "An error occurred while reading sectors and loading them into RAM ", 10, 13, 0

times 510 - ($-$$) db 0
dw 0xaa55
Then it comes the code that is bigger than 512 bytes that I have put in sector 1 (index 0) I call the file message.asm:

Code: Select all

[bits 16]
[org 0]

start:
	mov ax, cs ;AX points to CS (0)
	mov ds, ax ;Data segment is now pointing to (0)
	mov es, ax ;ES points to (0) too

	
mov si, A
call print
mov si, B
call print
mov si, C
call print
mov si, D
call print
mov si, E
call print
mov si, F
call print
mov si, G
call print
mov si, H
call print
mov si, I
call print
mov si, J
call print
mov si, K
call print
mov si, L
call print
mov si, M
call print
mov si, N
call print
mov si, O
call print
mov si, P
call print
mov si, Q
call print


mov ah, 0	;Wait for key press
int 16h
int 19h		;Reboot but leave memory to where is pointing so we can continue with our normal boot

print:
	pusha	;Store all general-purpose registers on the stack
	mov bp, sp	;Allocates in stack program variables
	iterate:
		lodsb	;Loads 8bit byte address from SI register to work with strings
		or al, al	;Logic or to check if string already reached its end "0"
		jz done_writing
		mov ah, 0x0e	;To print character into screen
		mov bx, 0
		int 10h
		jmp iterate
	done_writing:
		mov sp, bp	;Get variables out of stack
		popa		;Retrieve all general-purpose registers of the stack with order LIFO ignoring SP
		ret 

A db    "           ___     ___     ___     ___     ___     ___     ___     ___ ", 10,13,0
B db    "       ___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___", 10,13,0
C db    "      /   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \ ", 10,13,0
D db    "      \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/ ", 10,13,0
E db    "      /   \___/                                                   \___/   \ ", 10,13,0
F db    "      \___/                                                           \___/ ", 10,13,0
G db    "      /   \                                                           /   \ ", 10,13,0
H db    "      \___/                Welcome to my bootloader!                  \___/ ", 10,13,0
I db    "      /   \                   Under construction                      /   \ ", 10,13,0
J db    "      \___/                                                           \___/", 10,13,0
K db    "      /   \                Press any key to continue                  /   \ ", 10,13,0
L db    "      \___/                   with normal boot.                       \___/ ", 10,13,0
M db    "      /   \___                                                     ___/   \ ", 10,13,0
N db    "      \___/   \___     ___     ___     ___     ___     ___     ___/   \___/ ", 10,13,0
O db    "      /   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \ ", 10,13,0
P db    "      \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/ ", 10,13,0
Q db    "          \___/   \___/   \___/   \___/   \___/   \___/   \___/   \___/ ", 10,13,0
Here you have a screenshot:
Bootloader1.jpg
Bootloader2.jpg
The second image was that I put it in a pen drive and booted the computer with it and the first one is in the Virtual Machine.

I still don't know how to display the MBR in the screen :( . I could make this program to read it and store those 512 bytes it in say 0x3000, but then I don't know how to recursively access each byte from there. For example byte at position 0x3000:0000, then 0x3000:0001 and so on since those addresses are in hex and I have no idea on how to make a counter in hex since CX only counts integers.

Oh, if anyone mind, here are a few of the sources I've read before reaching that. I've read more but I don't have the links, sorry. The first link is pretty much what helped me. If it weren't for it I wouldn't have been able to get past the 512 bytes and load disk sectors correctly:
http://appusajeev.wordpress.com/2011/01 ... e-os-nasm/
http://www.assembly.happycodings.com/code7.html
http://www.htl-steyr.ac.at/~morg/pcinfo ... te6xo0.htm
http://www.skynet.ie/~darkstar/assembler/tut3.html
http://www.petesqbsite.com/sections/tut ... rial2.html
http://jwball.co.uk/2011/04/writing-tex ... real-mode/
http://geezer.osdevbrasil.net/osd/cons/index.htm
http://www.ragestorm.net/blogs/?p=18
http://frdsa.fri.uniza.sk/~janosik/Vyuk ... cture7.pdf
http://www.programmingforums.org/thread17429.html
http://www.osdever.net/tutorials/view/g ... evelopment
http://www.cs.virginia.edu/~evans/cs216/guides/x86.html
http://linuxgazette.net/issue77/krishnakumar.html
http://www.supernovah.com/Tutorials/Kernel1.php
https://en.wikibooks.org/wiki/X86_Assem ... nd_64_Bits
http://www.oocities.org/codeteacher/x86 ... l1012.html
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 »

Finally! It's working! I forgot about the code Brendan gave me because I ignored it in the first place because I didn't wanted to just copy paste it. Anyway, the code does show the first boot sector now. Here is what I've done to dump the first boot sector into screen. I've changed some comments on Brendan's code and the structure of the instructions so I could understand them better. For example, Brendan's code make 2 mov in only 1 instruction but I prefer to separate them to see what's going on:

Code: Select all

%define store_location 0x1000
%define drive 0x80
%define code_sector_location 1 ;This is index 0 so we are actually pointing to sector 1.

bits 16
org 0x7c00

jmp start

start:

   mov ax, cs   ;AX points to CS 0x7c0
   mov ds, ax   ;DS points to 0x7c0
   mov es, ax   ;ES contains what is on 0x7c0

   mov al, 03h   ;Text mode 25x80
   mov ah, 0
   int 10h
   
   mov ax, store_location
   mov ds, ax	;We will print our read sector from DS:SI so we need DS to point to the correct location
   mov es, ax   ;Point ES to store_location (top of our stack)
   mov cl, code_sector_location
   mov al, 1   ;Number of sectors to read

   call read_sectors   ;Load sectors and put them into RAM address of store_location
 
   
   mov si, 0           ;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). The loop will execute 8 times

read_sectors:
   mov bx, 0
   mov dl, drive
   mov dh, 0   ;Head to read
   mov ch, 0   ;Track to read
   mov ah, 2   ;To read sectors
   int 0x13
   jc error_reading
   ret
   error_reading:
      mov si, error_msg
      call print
      mov ah, 0   ;Wait for key press
      int 16h
      int 19h      ;Reboot but leave memory to where is pointing   
   
print_line:
    call print_data
    loop print_line
	
	mov ah, 0   ;Wait for key press
      int 16h
      int 19h      ;Reboot but leave memory to where is pointing
	
print_data:
    push cx					;Store cx current value so we can still count the lines to print when we get out of our next loop of printing 64 characters
    mov cx,64               ;Loop 64 times
    cld						;Clear direction flag to read DS:SI string from left to right.
next_char:
    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_char
done:
    mov ax, 0x0E0A           ;Newline
    int 0x10
    mov ax, 0x0E0D           ;Carriage return
    int 0x10

    pop cx
    ret

print:
   pusha   ;Store all general-purpose registers on the stack
   mov bp, sp   ;Allocates in stack program variables
   iterate:
      lodsb   ;Loads 8bit byte address to work with strings
      or al, al   ;Logic or to check if string already reached its end "0"
      jz done_writing
      mov ah, 0x0e   ;To print character into screen
      mov bx, 0
      int 10h
      jmp iterate
   done_writing:
      mov sp, bp   ;Get variables out of stack
      popa      ;Retrieve all general-purpose registers of the stack with order LIFO ignoring SP
      ret

error_msg db "An error occurred while reading sectors and loading them into RAM ", 10, 13, 0

times 510 - ($-$$) db 0
dw 0xaa55
As promised I will make a tutorial explaining step by step every line of code as soon as I organize myself. This is going to take some time and I don't think I will go deep into theory, just the code and every line explanation. I'm thinking about making some drawings too to explain what is going on on the system after the execution of each instruction. Maybe some drawings pointing the current values of registers at each line of code. For example, an image with DS register value after executing mov ax, store_location and then mov ds, ax

BTW, the original question of this thread, I still don't know the answer. I would say it's impossible unless one choose specific values for the drive and try to read such a drive with int 13h. Then according to the carry flag it may be possible to assume whether that disk exists or not.

Thanks everyone for all your help! :D
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

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

Post by Nessphoro »

Braceq wrote: As promised I will make a tutorial...
Please don't.
You obviously don't know what you are talking about, and lack the required knowledge.
And some remarks just make me want to suicide as a developer and programmer.
since those addresses are in hex and I have no idea on how to make a counter in hex since CX only counts integers.
I mean really?

Here is my advice, mate, go read a book on computers, then on assembly and then read it again.
I don't want to sound rude, just pointing out the facts.
The OSDev community doesn't need another copy-pasted tutorial from an author who barely knows how, and why it works.

By all means I'm not saying you should stop OSDeving, I'm merely asking you to not poison the new members' minds with this.

Cheers.
Post Reply