Search code examples
x86x86-16memory-segmentation

Is there a standard way to figure out a seg:off representation of a physical address in real mode?


So, I know that the physical address of segment:offset is equal to segment * 0x10 + offset, but how do I do that the other way around?

Like if I had an address 0x1038 what would the formula be for converting that linear physical address to a segment:offset segmented address.


Solution

  • (it's 0x10 and not plain 10, just to make sure we are on the same page.)

    It depends on the context, there are many different ways to address the same memory location this way. In fact, there are 0x1000 (4096) ways1.

    Segment = Address >> 4, Offset = Address & 0xF would be one way, Segment = (Address & 0xF0000) >> 4, Offset = Address & 0xFFFF would be another, but there are many, many more.

    This is because the ranges of segment and offset in terms of bits of the final address overlap:

      SSSS   Segment
    +  OOOO  Offset
    ----------------
    = AAAAA  Address
    

    So, the address 0x12345 could be represented by all of these segment/offset pairs:

    0235:FFF5
    0236:FFE5
    0237:FFD5
    ...
    0FFD:2375
    0FFE:2365
    0FFF:2355
    1000:2345
    1001:2335
    1002:2325
    1003:2315
    ...
    1232:0025
    1233:0015
    1234:0005
    

    Of course it's easy if you already know what the segment or the offset should be - then you can use simple algebra to calculate the other.


    1: This doesn't hold true near the lower end of the address spectrum (below 0x0FFF0) where some combinations of segment and offset would result in a physical address larger than 0xFFFFF and could only be used to represent a low address if there is no active 21st address line (A20), causing addresses to wrap, otherwise there would be fewer ways to represent the same address.