В дополнение к переименованию регистров, чтобы скрыть пузырьки из-за задержек инструкций, большинство архитектур x86 достаточно умны, чтобы подсчитывать нажатия и всплески и переименовывать их в регистры. Помните, что декодер команд на x86 фактически выполняет своего рода JIT-компиляцию, превращая поток команд x86 в небольшую программу микрокода, хранящуюся в кэше трассировки. Часть этого процесса включает перехват загрузок стека с небольшим смещением и преобразование их в регистры. Таким образом что-то вроде (явно глупо и чисто, например):
lwz eax,[ebp]
lwz ebx,[ebp+4]
add eax,[edx+0]
push eax
lwz eax,[ebp+8]
add eax,ebx
pop ebx
add eax,ebx
готовит что-то вроде (представьте, что внутренние регистры называются например, r0..r16):
lw r3, edx
lw r1, ebp
lw r2, ebp+4 ; the constant '4' is usually stored as an immediate operand
add r1,r2
or r4,r1,r1 ;; move r1 to r4
lw r1, ebp+8
add r1,r2
or r2,r4,r4
add r1,r2
Конечно, магически умный декодер (в отличие от того, который фактически вписывается в счетчик транзисторов) может разрушить некоторые ненужные движения, но я хочу сказать, что push / pop и сохраняет / загружает в esp+(some small number)
на самом деле превратился в теневые регистры.