Why can’t you call a pointer address from the EBP register? What I mean by this is demonstrated in the follow code pattern.
- OpCode: ‘0xFF 0x10’ -> CALL DWORD PTR DS:[EAX]
- OpCode: ‘0xFF 0x11’ -> CALL DWORD PTR DS:[ECX]
- OpCode: ‘0xFF 0x12’ -> CALL DWORD PTR DS:[EDX]
- OpCode: ‘0xFF 0x13’ -> CALL DWORD PTR DS:[EBX]
- OpCode: ‘0xFF 0x14’ -> CALL DWORD PTR SS:[ESP+EDI]
- OpCode: ‘0xFF 0x15 0x012345678’ -> CALL DWORD PTR DS:[0x012345678]
- OpCode: ‘0xFF 0x16’ -> CALL DWORD PTR DS:[ESI]
- 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.)
You can call via EBP, its just encoded differently. You need the sequence
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 0x14example — 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 of0x3c— you want the 3rd byte to be0x24to get just ESPAs 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.