Whats With 0x07C0 and 0x07C00

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.
Post Reply
pskyboy

Whats With 0x07C0 and 0x07C00

Post by pskyboy »

Hey Guys

When i jump to my protected mode code bit and work out the location of my GDT table in memory. If i use 0x07c0 it won't get into P-Mode yet if i use 0x7C00 it will.

This seems very odd as i am setting my data and code segments when i boot up to 0x07C0. Can anyone tell me what the difference between the two is and why they have to be used in the two different places.

Peter
Curufir

Re:Whats With 0x07C0 and 0x07C00

Post by Curufir »

See this thread http://www.mega-tokyo.com/forum/index.php?board=1;action=display;threadid=2203 for some information about segmented to physical address translation which is the problem you've got.

Curufir
pskyboy

Re:Whats With 0x07C0 and 0x07C00

Post by pskyboy »

hmm i kind of only half get it.

so when you do a 0xaddr:addr

is it segment:offset or offset:segment

im guessing its the first which means 0x07C0 is the segment oh yeah this makes sense. Okay so surely the actually address of the first byte in this segment is 0xFFFF * 0x07C0 since each segment is 64kb? is this correct.
pskyboy

Re:Whats With 0x07C0 and 0x07C00

Post by pskyboy »

Okay i have finally got this

Talk about being slow.

Now in order to gain a bit of ego back im going to do my best to explain it so other people who don't get it will understand it. It also gives me the chance to get what i think is going on checked, so if im wrong correct me.

Take this one as an example the address of 1mb is 0x100000 this is the actual physical address. When this is converted to segment:offsets though this will be the 16th Segment as 16 * 64 = 1024Kb (does that number look familar). So as you can see in order to get the segment adress of a physical address divide the address by 64 if its in Kb or 65536 if its in bytes. This will then give you the integer segment. ie. the whole number is the segment. In order to get the offset you then need to mulitply the segment adress you just got by 64kb or 65536bytes and subtract this from your physical adress.

In order to convert the other way you need to times the segment by 64kb or 65536bytes(again depending on wether your working in bytes or Kb) and then add on the offset.

Hope this is right and helps other people
took me long enough to get :)

Peter
Schol-R-LEA

Re:Whats With 0x07C0 and 0x07C00

Post by Schol-R-LEA »

Unfortunately, this isn't right. It's too bad, too, as this is the way most people expect it to work, and is a lot easier to understand than the actual mechanism that is used.

I will do my best to explain this. If you can, try to pick up a copy of Assembly Language Step by Step (see the book thread for details), as Duntemann explains it better than anyone I know of. You may want to look at a more detailed explanation which I gave in an earlier thread (reply #23).

Real mode segment base:offset addressing is designed as a way to represent a 20-bit absolute address as two 16-bit addresses. The idea was that, for most programs, the segment base values would be held in the appropriate segment registers (CS for code segments, DS for data segments, SS for stack segments, and ES for extra data segments), and the local addresses used as an offset from the segment base.

The clever (and annoying) part is in how the addresses are combined. The Intel designers knew that the 8086 would only have 20 address lines, and so wanted to have as little excess addressing capacity as possible. Also, they wanted to make sure that there were no large gaps between the beginnings of one segment boundary and another. So they devised a system of segment arithmetic in which the segment base is shifted 4 bits to the right (or multiplied by 16, depending on how you look at it), and the offset then added to that value:

9ED0:8109 becomes
[tt]
9ED00 segment base * 0x0010
+8109 segment offset
------
A6E09 absolute address
[/tt]

A few things should be noted about this system. First, you need to realize that segments are not fixed areas of memory; there is no 'segment 0', segment 1', 'segment 2', etc. Segments are defined as needed by a value in a segment register (or the base of a FAR address), and any base value can be used. A segment base may begin at any address that is an even multiple of 16, but when there is no base pointing to a given area of memory, there is no segment there.

Second, as a corollary of this, real mode segment sizes are defined implicitly by the actual usage of them; a real mode segment may be any size between 1 and 65536 bytes. (This changes in protected mode, of course). To put it another way, every segment base has a corresponding set of potential offsets, starting with 0x0000 and going up to 0xFFFF, but a segment is not automatically 64K in size.

The third important factor is that segments can overlap with each other, either in whole or in part. This means that you can have Code, Data and Stack memory all within what is effectively a single segment, by setting CS == DS == SS. It also measn that, except for the very first 16 bytes of the real address space (and the very last, though on the 8086 they are not accessible), every absolute address can be represented with more than one base:offset pair. To take the earlier example,

[tt]A6E09 == 9ED0:8109 == A6E0:0009 == 97C8:F189[/tt]

and so forth. I recommend trying to add different base:offset pairs together by hand to see for yourself how this works.

I hope that I have clarified more than I have confused with this. If you don't get it immediately, don't worry; this is one of the most confusing aspects of the x86 family, and it usually takes a while for it to sink in. Feel free to ask for any further clarification. Again, I recommend Duntemann's book for it's excellent explanations on this point.
Curufir

Re:Whats With 0x07C0 and 0x07C00

Post by Curufir »

Schol-R-Lea's explanation fills in all the gory technical details so nothing further is needed. I just wanted to suggest this particular scheme which I use myself for visualising real mode memory placement.

linear -> segment:offset
segment = quotient of linear/16
offset = remainder of linear/16

Note: This yields just one of many possible segment:offset addresses, others will also be valid.

So for a hexadecimal linear address the last digit is the offset, the other digits are the segment. Space fill both segment and offset with zeros on the left side to make the full address.

eg
0x8bed2 = 0x8bed:0002
0x7c00 = 0x07c0:0000

This scheme will hold until you go above 1mb, at which point an alternative translation scheme must be used for obvious reasons.
pskyboy

Re:Whats With 0x07C0 and 0x07C00

Post by pskyboy »

Cheers Guys

This makes sense now and i have got my Bootloader working. I finallky realised it was *16 while i was doing my bootloader and it worked i then came on here and it clarified just why it was 16.

I think it would be good if this could go in a beginner notes thread or somehting as this caused me a lot of problems and if i had realsed to start with would of saved me a lot of time.

Cheers
Peter
Post Reply