Basically, anything that involves changing segments is slower, sometimes significantly so; this is unsurprising since descriptors have to be checked, privilege levels potentially changed etc. Other operations are unchanged. In particular, segment limit checks on memory accesses don’t affect the clock cycle count. Programs which don’t call the operating system often, and don’t change segments much, won’t see much difference in performance; programs which do, will. In particular, programs which often change DS
and ES
(e.g. to access video memory using string instructions) will suffer a lot if they’re not adapted for protected mode (but such patterns don’t translate well to a protected environment anyway). Interrupts are also more expensive.
The iAPX 286 Programmer’s Reference gives clock cycle counts for each instruction, in Appendix B; cases where protected mode execution affects the clock cycle counts are marked with “pm”. For example, an inter-segment call with an immediate 4-byte address takes 13 cycles in real mode, 26 cycles in protected mode. Some instructions have variants which only apply to protected mode; these aren’t explicitly marked “pm”, because their cycle count doesn’t vary, but they typically take far longer than non-protected-mode variants. For example, calls through call gates take at least 41 cycles; calls through TSSes take at least 177 cycles; etc.
There aren’t all that many instructions identified as such:
Instruction |
Real mode |
Protected mode |
CALL |
7–16 |
7–185 |
INT |
23 |
40+ |
IRET |
17 |
31+ |
JMP |
7–15 |
7–183 |
LDS /LES |
7 |
21 |
MOV into a segment register |
2–5 |
17–19 |
POP into a segment register |
5 |
20 |
RET |
11–15 |
11–55 |
To understand the impact, consider the CALL
instruction in detail:
Variant |
Clocks |
Call near, offset relative to next instruction |
7 |
Call near, offset absolute at EA word |
7 from a register, 11 from memory |
Call inter-segment |
13 in real mode, 26 in protected mode, +3 if indirect¹ |
Call gate, same privilege |
41, +3 if indirect |
Call gate, more privilege, no parameters |
82, +1 if indirect |
Call gate, more privilege, x parameters |
86 + 4x, +4 if indirect |
Call via Task State Segment |
177, +3 if indirect |
Call via task gate |
182, +3 if indirect |
- Calls within the same segment don’t vary depending on the protection mode; the only variation is related to memory accesses.
- Calls to another segment, with no possible privilege change (“Call inter-segment”), are twice as expensive in protected mode — the new segment descriptor needs to be checked against the current privilege level.
- Calls to a call gate, which is how the 286 implements system calls, are three times more expensive if the call doesn’t result in a privilege change, and at least six times more expensive if the call does result in a privilege change. When a call gate changes to a more privileged state, a number of values are copied to a new stack; call gates can also specify that parameters should be copied too, which is why their cost varies depending on the number of parameters. (Parameters are callee-specified.)
- Calls to a task gate, which is how the 286 implements hardware-mediated task switching, are far more expensive, because the entire task context must be stored.
The Intel manual provides detailed explanations of all the checks and operations involved in the various scenarios.
INT
and JMP
all have the same potential costs. IRET
and RET
need to undo whatever changes the corresponding INT
and CALL
operations made, hence their costs. LDS
, LES
, MOV
and POP
can’t change privilege levels, so the cost variation there is similar to the “basic” inter-segment call/jump variation.
The fact that segment limit checks, which apply to all memory accesses, don’t cause the cycle counts to vary can be surprising. But the checks are made all the time, whether in real mode or in protected mode; real mode is really a degenerate variant of protected mode, where segment loads aren’t checked but update the shadow segment descriptors to match the 8086’s memory model. This is what allows LOADALL
to work. See also Will the real Real Mode please stand up?
¹ I suspect the Intel manual is wrong here; it says “16,mem=29” for the ed variant, but that should really be “16,pm=29”.
lp: MOV DS,CX / LODSW / MOV DS,BP / ADD AX,[BX+SI] / STOSW / LOOP lp
would take 2+5+2+7+8 cycles (24 cycles total). Protected mode would add an extra 30 cycles per iteration.