Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't you set the instruction pointer directly?

People also ask

What does the instruction pointer do?

The Program Counter, also known as the Instruction pointer, is a processor register that indicates the current address of the program being executed.

How do I set up an EIP register?

Setting eip to a register is as simple as jmp eax . You can also do push eax; ret , which pushes the value of eax to the stack and then returns (i.e. pops and jumps). The third option is call eax which does a call to the address in eax.

How do I edit my EIP?

You can alter your order to be pushed Manually or in Automatic action anytime before the scheduled date. Click the CHG button on the Action column of your EIP schedule to start editing. Click the CHANGE button when you are done selecting. Press the MODIFY button when you are done editing.

What is EIP Linux?

EIP is the instruction pointer. It points to (holds the address of) the first byte of the next instruction to be executed. ESP is the stack pointer. It points to (holds the address of) the most-recently pushed value on the stack.


You can't access it directly because there's no legitimate use case. Having any arbitrary instruction change eip would make branch prediction very difficult, and would probably open up a whole host of security issues.

You can edit eip using jmp, call or ret. You just can't directly read from or write to eip using normal operations

Setting eip to a register is as simple as jmp eax. You can also do push eax; ret, which pushes the value of eax to the stack and then returns (i.e. pops and jumps). The third option is call eax which does a call to the address in eax.

Reading can be done like this:

call get_eip
  get_eip:
pop eax ; eax now contains the address of this instruction

That would have been a possible design for x86. ARM does expose its program counter for read/write as R15. That's unusual, though.

It allows a very compact function prologue/epilogue, along with the ability to push or pop multiple registers with a single instruction: push {r5, lr} on entry, and pop {r5, pc} to return. (Popping the saved value of the link register into the program counter).

However, it makes high-perf / out-of-order ARM implementations less convenient, and was dropped for AArch64.


So it's possible, but uses up one of the registers. 32-bit ARM has 16 integer registers (including PC), so a register number takes 4 bits to encode in ARM machine code. Another register is almost always tied up as the stack pointer, so ARM has 14 general-purpose integer registers. (LR can be saved to the stack, so it can be and is used as a general-purpose register inside function bodies).

Most of modern x86 is inherited from 8086. It was designed with fairly compact variable-length instruction encoding, and only 8 registers, requiring only 3 bits for each src and dst register in the machine code.

In the original 8086, they were not very general-purpose, and SP-relative addressing isn't possible in 16-bit mode, so essentially 2 registers (SP and BP) are tied up for stack stuff. This leaves only 6 somewhat-general purpose registers, and having one of them be the PC instead of general-purpose would be a huge reduction in available registers, greatly increasing the amount of spill/reload in typical code.


AMD64 added r8-r15, and the RIP-relative addressing mode. lea rsi, [rip+whatever], and RIP-relative addressing modes for direct access to static data and constants, is all you need for efficient position-independent code. Indirect JMP instructions are totally sufficient for writing to RIP.

There isn't really anything to be gained by allowing arbitrary instructions to be used to read or write the PC, since you can always do the same thing with an integer register and an indirect jump. It would be almost pure downside for x86-64's R15 to be the same thing as RIP, especially for the architecture's performace as a compiler target. (Hand-written asm weird stuff was already very much an uncommon niche thing by 2000, when AMD64 was designed.)

So AMD64 is really the first time that x86 could plausibly have gained a fully-exposed program counter like ARM, but there were many good reasons not to do that.


jmp will set the EIP register.

this code will set eip to 00401000:

mov eax, 00401000
jmp eax ;set Eip to 00401000

and for getting EIP

call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret

I think they meant that the IP register cannot be accessed directly in the same way the other registers are accessed. Programmers can definitely write to IP, for example by issuing a jump instruction.