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.
(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.