3
votes

Why can't you call a pointer address from the EBP register? What I mean by this is demonstrated in the follow code pattern.

  1. OpCode: '0xFF 0x10' -> CALL DWORD PTR DS:[EAX]
  2. OpCode: '0xFF 0x11' -> CALL DWORD PTR DS:[ECX]
  3. OpCode: '0xFF 0x12' -> CALL DWORD PTR DS:[EDX]
  4. OpCode: '0xFF 0x13' -> CALL DWORD PTR DS:[EBX]
  5. OpCode: '0xFF 0x14' -> CALL DWORD PTR SS:[ESP+EDI]
  6. OpCode: '0xFF 0x15 0x012345678' -> CALL DWORD PTR DS:[0x012345678]
  7. OpCode: '0xFF 0x16' -> CALL DWORD PTR DS:[ESI]
  8. OpCode: '0xFF 0x16' -> CALL DWORD PTR DS:[EDI]

'5' is noted in "Intel Instruct manual" but '6' is never directly referred to and it is never explicitly stated that you cannot call it from the EBP register. I know this isn't a useless feature but I was wondering why Intel choose those two registers to utilize, was it just a design choice or is their something I am missing? (I have a guess but I'm curious what the real reason is.)

1

1 Answers

4
votes

You can call via EBP, its just encoded differently. You need the sequence

0xff 0x55 0x00

The thing is that there's no way to encode EBP without an offset (the above specifies EBP with a byte offset of 0), as the encoding that you'd normally expect to be EBP without an offset (0x15) instead means 32-bit absolute.

Also note your 0xff 0x14 example -- in that case there's a 3rd byte (a SIB byte) that encodes a base register, index register, and a scale factor. ESP+EDI like your example has a 3rd byte of 0x3c -- you want the 3rd byte to be 0x24 to get just ESP

As to why they chose EBP and ESP as the registers that can't be encoded simply, its because ESP is the stack pointer (so is normally accessed by push/pop instructions) while EBP is the frame pointer, so you rarely want to dereference it directly without an offset. At least that was the case when the 80386 was designed.