1

physical address=16*selector+offset
but i don't know why multiplying 16 by selector?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
sia
  • 401
  • 3
  • 8
  • 20
  • 1
    You need to provide more information. At a minimum, what CPU architecture and assembler are you using? – bta Jun 23 '10 at 21:03
  • of course i don't use 16 bit, i just saw that on a book and i'm just curious about it! so is it a general formula for all 16 bit real modes or what? – sia Jun 23 '10 at 21:14
  • no, if you refer to x86, and provided the formula is right, this can't be general. – ShinTakezou Jun 23 '10 at 21:16

4 Answers4

4

In order to be "programmer-compatible" with the Z80, yet still be able to use more than 64 kiB of memory, early Intel processors introduced memory segmentation. The 16-bit segment would be shifted left 4 bits (meaning multiplication by 16, and not 64 as your question claims) before being added to the 16-bit offset, resulting in a 20-bit address.

For programmers accustomed to the Z80, all that was required was to use the segments provided by the OS, and they would be able to use the given 64 kilobyte offset as they pleased. New programmers could do more sophisticated manipulation of the segments, allowing them to access 1 MiB of address space (the IBM PC cut it down to 640 kiB, but for their own reason).

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Somehow I don't think they cared about being Z80 compatible, as the Z80 was their direct competition. The instructions weren't even 8080 compatible, although translation was relatively easy. – Mark Ransom Jun 23 '10 at 21:31
  • @Mark: Of course they cared. If they were moderately Z80-compatible then it'd another bullet point that they could add. One that could pull Z80 developers their way. – Ignacio Vazquez-Abrams Jun 23 '10 at 21:36
  • @Ignacio: The Z80 was a batch of odd extensions on the 8080, and I don't remember most of those extensions going into the 8086 and 8088. There was nothing that caught on that was particularly upwards compatible from the Z80. – David Thornley Jun 23 '10 at 21:41
  • @David: The memory addressing scheme. x86 programmers these days don't have to worry about descriptor tables in protected mode thanks to the operating system. Replace "x86" with "Z80", "descriptor tables" with "memory segments", and "protected mode" with "the 8086", and history repeats itself. – Ignacio Vazquez-Abrams Jun 23 '10 at 21:50
  • @Ignacio: The Z80 addressed memory much like the 8080. The difference was a pair of index registers, IX and IY, which were clumsy and slow attempts to allow indexing. I found them mostly useless, and that seemed to be the general consensus from what I read. The Z80 didn't have memory segments. In short, from a good deal of Z80 experience some decades ago, I have no idea what you're talking about. – David Thornley Jun 23 '10 at 22:00
  • @David: Exactly. The Z80 didn't have memory segments. And the 8086 could be treated as though it didn't have memory segments either, as long as you were willing to compromise. – Ignacio Vazquez-Abrams Jun 23 '10 at 22:11
  • @Ignacio: And the 8080 didn't have memory segments, either. I'm completely failing to see where the Z80 comes in here. The 8086 and 8088 were assembly-compatible with the 8080. The very first BASIC for the IBM PC was actually a touch slower than the equivalent on a fast 8085, since it was simply reassembled. – David Thornley Jun 24 '10 at 14:00
3

The goal with the 8088/8086 was to provide a means by which a 16-bit processor could have a 1-megabyte addressing space, without programmers having to divide the address space into 64K chunks and worry about whether addresses crossed the boundaries between them. Though it has been much maligned, it is actually better than any other approach I've seen for working with addresses that exceed the register size. It often works relatively effortlessly in cases where data are naturally subdivided into items are 64K or less, and where it is acceptable to pad items to begin on 16-byte boundaries. The multiplication by 16 (instead of some larger or smaller number) was probably arbitrary, but it works out conveniently when listing things in hexadecimal notation, and it was a good compromise between using two small a number (which would have limited the address space to half a meg or less) or too large a number (which would have required more code to either deal with arbitrary offsets for allocated blocks, or else waste more memory padding blocks to a larger multiple).

The only major deficiencies in the 8088's segmentation design, really, are:

  1. Two general-purpose segmentation registers aren't "quite" enough. A common pattern is "copy data from one object to another object, using a third object to translate it"; that pattern can only be implemented efficiently if one of the objects lives in either the code segment or on the stack. It's unfortunate this wasn't fixed until the 80386, where common practice was to ignore segments.
  2. There wasn't any nice way to do any sort of arithmetic on segment registers. Instructions to add or subtract 0x1000 from DS or ES (or FS or GS), either if carry was set or unconditionally--eight (or sixteen) opcodes total--would have greatly facilitated segment handling.
  3. There should have been "mov seg,immediate" instructions.

Even though programmers often grumbled about the 8088/8086 back in the day, it was far better than any other 16-bit processor I've seen then or since (nb: I consider the 68000 a 32-bit processor).

supercat
  • 77,689
  • 9
  • 166
  • 211
2

64? Sure? Read e.g. wikipedia. Multiplying by 64 is like shifting left by 6 bits (wikipedia says it should be 4, i.e. *16), i.e. is like saying the selector represents the most significant 16 bits of a 22 bits address (wikipedia reports 20). This is real mode as decribed in wikipedia too (better than I can do).

ShinTakezou
  • 9,432
  • 1
  • 29
  • 39
1

i don't know why multiplying 64 by selector?

A 16-bit pointer can easily address 64 KB.

The CPU designers wanted to be able to address 1 MB.

So instead of using a single 16-bit pointer, they specified that a pointer would be implemented by two registers, i.e. segment-plus-offset, where 'segment' is a 16-bit register whose value is multiplied by 16 in order to address the 1 MB.

The value (16) comes from dividing the desired address range (1 MB) by the natural addressibility of the 16-bit register size (64 KB) ... i.e. 16 come from 1 MB / 64 KB.

ChrisW
  • 54,973
  • 13
  • 116
  • 224