3
votes

All x86 cpu's have Instruction pointer register which holds the offset (address) of next instruction to be fetched for execution. Providing there is no branching or jumps what is the typical amount which is incremented (or decremented) for the next instruction to fetch? I would think it would be the size of a typical instruction perhaps 32 bits?

1

1 Answers

9
votes

It cannot simply increment it by the size of a "typical" instruction because there is no such thing as a "typically-sized" instruction in the x86 architecture. Instructions have all kinds of weird, varying sizes, as well as the possibility for various optional prefixes. (Although there is an upper bound: instructions can only consist of at most 15 bytes.)

Although many popular RISC processors use a fixed-width encoding for instructions (Alpha, MIPS, and PowerPC all have fixed-size 32-bit instructions, while Itanium has fixed-size 41-bit instructions), Intel x86 uses a variable-width encoding, primarily for historical reasons. It is a very complicated ISA!

A generalized encoding schema for the various components of an x86 instruction.
(Image taken from Igor Kholodov's lecture notes: http://www.c-jump.com/CIS77/CPU/x86/lecture.html)

Thus, the processor has to have internal logic that updates the instruction pointer (IP) as part of its instruction decoding process. It fetches the instruction, decodes it, and increments the instruction pointer by the actual size of the decoded instruction. (That is, from the programmer's high-level perspective. Internally, things are even more complicated, thanks to speculative execution.)

Because instruction decoding is so complicated, a lot of silicon has to be devoted to doing this. On the low-power Atom processor, around 20% of the total power consumption comes just from decoding instructions. However, there is at least one benefit to this complexity: increased instruction density. Variable-length instruction encoding means that certain, commonly-used instructions can be encoded using only a few bytes, and therefore take up very little space in the instruction cache. So you have a classic engineering trade-off where, while the instruction decoder is larger and more complicated, the instruction cache can be made smaller and therefore cheaper.

Note that the instruction pointer is never decremented in normal, "straight-line" decoding. Unlike the stack, the instruction stream grows upward in memory. A decrement would only happen as a result of a branch, which your question explicitly put off-limits. But I'll break the rules and point out that, when a branch is executed (e.g., via an unconditional jmp, a conditional jump, or a call), the instruction pointer is explicitly changed to match the target of the branch.