Sign in to follow this  
VanillaSnake21

why does 0000:0010 == 0001:0000

Recommended Posts

Hi, Why I'm reading a chapter in an asm tutorial that explains mem segmentation in real mode. The author is saying that segments overlap and gives this as an example, 0000:0010 same as -> 0001:0000. Also this " 0000:0010 = 0*16 + 1*16 " i get this part, but then he goes on 0001:0000: (16 * 1 + 16*0 = 16 + 0 = 16) I don't get why 0001 == 1*16, doesn't the first bit correspond to 16^0, so isouldn't it be 1 (16^0 * 1 = 1). Thanks.

Share this post


Link to post
Share on other sites
It's "address = segment * page size + offset" where in "0000:1111" 0000 is the segment and 1111 is the offset. In this case page size is 16, or 0x10 hex.

Basically it's a waste of the 12 bits that overlap:

0000:0010 = (0 * 16 + 0x10) = 0x10

0001:0000 = (1 * 16 + 0) = 0x10

0001:0002 = (1 * 16 + 2) = 0x12

0001:0200 = (1 * 16 + 0x200) = 0x210

Share this post


Link to post
Share on other sites
In the segment:offset model, each segment is a 16bit value. We
always multiply the current segment number by 16 (and add it to offset)
to get the absolute address.

ie:

segment:offset = segment*16 + offset = absolute address


In your first example, 0000:0010, we multiply using the above formula:

segment offset absolute address
0*16=0 + 0*16 + 1*16 = 16

For 0001:0000:

segment offset absolute address
1*16 + 0*16 = 16

Hence, 0001:0000 = 0000:0010.

The basic idea is to always multiple segment by 16. In the above,
the values given for offset is just the converstion from hex to int
(Which is what you were doing)

This is the way I learned it, anyway [smile]

Hope this helps!


Share this post


Link to post
Share on other sites
If relying purely on the concept i get it, segment * 16 + offset to get the address, but I don't get how the conversion works

using address 0001:0100

0001 is a word, so is 0010
so 0001h would come out to 16^0 = 1d?
and 0100h would come out to 16^2 = 32d?

but how come you're saying that 0001h = 16d?
then what does 0010h = ?

Share this post


Link to post
Share on other sites
What dont you understand?

0x0001:0x0100 =

segment offset
0x0001 : 0x0100

; multiply segment by 16 decimal (Size of segment)
0x0001 * 16 decimal = 16 decimal

; add result to offset:
16 decimal = 0x10

0x0100 + 0x10 = absolue address 0x110 (272 decimal)



0x0010:0010 is the same as 0x0001:0x0100, as the following shows:


segment offset
0x0010 : 0x0001

; multiply segment by 16
0x0010 * 16 (0x10) decimal = 0x100 (256 decimal)

; add result to offset
0x0010 = 16 decimal

256 decimal (segment) + 16 decimal (offset)
= absolute address 0x110 (272 decimal)


Notice how both 0x0010:0010 and 0x0001:0x0100 map to the same
absolute address (0x110)

You can easily verify this by using a calculator or Windows debug
to see they both map to the same location in memory:

-d 0010:0010
0010:0010 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0010:0020 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0010:0030 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0010:0040 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0010:0050 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..

-d 0001:0100
0001:0100 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0001:0110 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0001:0120 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0001:0130 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..
0001:0140 C5 26 00 F0 C5 26 00 F0-C5 26 00 F0 C5 26 00 F0 .&...&...&...&..


(Notice the values are exactally the same)

Hope this clairfies it a little[smile]

Share this post


Link to post
Share on other sites
Thanks :), I understand the concept, but what I was confused about is why 0001h was 16, because if you plug 0001h in a calc and convert to decimal you will get 1. I think that what I was missing is that the segment part of the address is actually a 20bit value, which is stored in 5 hex places, the reason they don't write out the fifth place is because it's always a 0. so 0001:0000 is actually a 00010:0000. Is that right? If so then it makes sense, since 00010 does equal 16 in the decimal system.

Share this post


Link to post
Share on other sites
Quote:

I think that what I was missing is that the segment part of the address is actually a 20bit value, which is stored in 5 hex places, the reason they don't write out the fifth place is because it's always a 0. so 0001:0000 is actually a 00010:0000.

Hence the reason we multiply the segment by 16[smile]

(I personally didnt know it had a 5th place though)

The reason 0001 = 16 decimal is because it is a segment.
All segments are multplied by 16, so 0x0001 * 16 = 16 decimal (0x10)
(That wouldnt apply if you added the 5th place, though)

Share this post


Link to post
Share on other sites
Quote:
The reason 0001 = 16 decimal is because it is a segment.
All segments are multplied by 16, so 0x0001 * 16 = 16 decimal (0x10)
(That wouldnt apply if you added the 5th place, though)


Are they really multiplied? 0001:0000 is 16 (or 0x10) because 00010 is 16.
So 0010:1010 would be 1* 16^2 + 1*16^3 + 1*16^1 = 1110h?

So I don't think it's simply multiplied it's more like converting the segment into a decimal and converting the offset into a decimal and then adding both.

Quote:
from Intro to 80x86 asm and comp archiecture
This means that one segment starts at address 00000, another (overlapping the first)
starts at address 16 (0001016), another starts at address 32 (0002016), etc. Notice that the starting
address of a segment ends in 0 when written in hex
. The segment number of a segment consists of the
first four hex digits of its physical address.


Quote:

As an example, 18A3:5B27 refers to the byte that is 5B27 bytes from the beginning of the segment
starting at address 18A30. Add the starting address and the offset to get the five-hex-digit address.
18A30 starting address of segment 18A3
+ 5B27 offset
1E557 five-hex-digit address

Share this post


Link to post
Share on other sites
There's no converting to decimal involved - you're making this way more complicated than it actually is.

in pseudocode:


int Segment = 0x0010;
int Offset = 0x1010;

SegmentPhysicalAddress = 0x0010<<1 = 0x0100
Segment:Offset = SegmentPhysicalAddress+Offset = 0x0100+0x1010 = 0x1110


That's really all there is to it. The segment registers only hold 16 bits, there isn't an invisible 5 hex digit being stored somewhere. The CPU just does what I described every time it translates a memory address.

Share this post


Link to post
Share on other sites
Quote:
Original post by cshowe
There's no converting to decimal involved - you're making this way more complicated than it actually is.

in pseudocode:


int Segment = 0x0010;
int Offset = 0x1010;

SegmentPhysicalAddress = 0x0010<<1 = 0x0100
Segment:Offset = SegmentPhysicalAddress+Offset = 0x0100+0x1010 = 0x1110


That's really all there is to it. The segment registers only hold 16 bits, there isn't an invisible 5 hex digit being stored somewhere. The CPU just does what I described every time it translates a memory address.


Yeah I got 1110h too, I was just saying for the sakes of clarity, that it's more like converting to a decimal rather then somply multiplying by 16, because if it's a 0010:0000 you would have to multiply by 256.

Actually it's not the final address that bothered me when i first posted but I couldn't get why 0001:0000 is the same thing as 0000:0010, because I didn't know that there's an unwritten 0 after 0001, and I was reading 0001 as 1 byte, when it's really 00010 which makes it 16 bytes. So if you go back from the current segment by 0001h (which is 16bytes) you have to go forward in the offset by the same amount and you will be at the same location except you'll be offsetting from the previous segment.

Share this post


Link to post
Share on other sites
What crypter means by multiplying by 16 is that your actually doing a left shift

0x0001 * 16 = 0x0010
0x0010 * 16 = 0x0100

Again there's no reason to even be using decimal numbers at all, the math works perfectly well in hex:

0x0001 * 0x10 = 0x0010
0x0010 * 0x10 = 0x0100


Also 0000:0010 corresponds to 0x0000 in a segment register and 0x0010 as the offset. 0001:0000 indicates 0x0001 in the segment register and 0x0000 as the offset. These are two different situations in the computer. In particular the segment registers hold different values. Yes both addresses point to the same place in physical memory, but the sequence of assembly instructions used to get there are different in each case.

If you want to state the 0000:0010 and 0001:0000 are equivalent then you are implicity comparing the final addresses - they aren't equivalent program states to be in. Don't think about an "invisible" zero after the segment. It's segement 0x0001 not segment 0x00010. The additional zero only comes about as part of the algorithm used to translate a segment:offset into a physical address.

Share this post


Link to post
Share on other sites
Quote:
Don't think about an "invisible" zero after the segment. It's segement 0x0001 not segment 0x00010. The additional zero only comes about as part of the algorithm used to translate a segment:offset into a physical address.


I posted this earlier, this is an excerpt from an assembly book...

Quote:

As an example, 18A3:5B27 refers to the byte that is 5B27 bytes from the beginning of the segment starting at address 18A30.

Here theyre saying that segment 18A3 starts at address 18A30.

Share this post


Link to post
Share on other sites
Yes, it's simply doing a hex left shift, which, as stated before, is the same thing as multiplying by 16 since the segment (think of it as an ordinal, if you will, which has to be converted into the base address by multiplying by sizeof(segment)) is given in hexadecimal. Here's a pretty cut and dry quote from the first hit off Google when searching about segment:offset addressing:

Quote:
Originally posted by Segment and Offset Memory Addressing

In x86 CPUs, memory addresses are composed of two parts: the segment address and the offset. These two are added together to produce the "real" address of the memory location, by shifting the segment address one hex digit to the left (which is the same as multiplying it by 16, since memory addresses are expressed in hexadecimal notation) and then adding the segment offset to it. (Yes, this is strange and not intuitive unless you are a PC programmer, and maybe not even then.) The address itself is often referred to using the notation segment:offset.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this