I'm working on an exercise in x86 assembly (using NASM) that has the niche requirement of limiting each instruction to a maximum of 3 bytes.
I'd like to call a label, but the normal way to do this (shown in the code example) always results in an instruction size of 5 bytes. I'm trying to find out if there's a series of instructions, 3 bytes or less each, that can accomplish this.
I've attempted to load the label address into a register and then call that register, but it seems like the address is then interpreted as an absolute address, instead of a relative one.
I looked around to see if there's a way to force call to interpret the address in the register as a relative address, but couldn't find anything. I have thought about simulating a call by pushing a return address to the stack and using jmp rel8
, but am unsure how to get the absolute address of where I want to return to.
Here is the normal way to do what I want:
[BITS 32]
call func ; this results in a 5-byte call rel32 instruction
; series of instructions here that I would like to return to
func:
; some operations here
ret
I have tried things like this:
[BITS 32]
mov eax, func ; 5-byte mov r32, imm32
call eax ; 2-byte call r32
; this fails, seems to interpret func's relative address as an absolute
... ; series of instructions here that I would like to return to
func:
; some operations here
ret
I have a feeling there may be a way to do this using some sort of LEA magic, but I'm relatively new to assembly so I couldn't figure it out.
Any tips are appreciated!
mov eax, func; call func
indeed uses absolute address but that should still work. Unless you load the code elsewhere than where it was assembled for. In that case you want position independent code. Howevermov eax, func
will again be 5 bytes exceeding your limit. – Mesarchcall
that is exactly the one you want to avoid. Depending on your exact requirements and environment (e.g. executable stack) you can cheat by creating longer instructions dynamically :) – Mesarchmov eax, func
;call eax
is correct. If that doesn't work (after linking), you're building your code wrong. Related (maybe duplicate): Shorter x86 call instruction -mov eax, func
is a win when amortized over two 2-bytecall eax
instructions. – Exegeticsmov eax, func
is a 5 byte instruction. The OP is doing this where the maximum instruction size is 3 bytes. This question isn't a duplicate of the one you show. The OP isn't trying to find the shortest encoding, but an encoding where no one instruction exceeds a 3 byte encoding but still can call a function. – Bridesmaidcall eax
fails. Obviouslymov eax, immediate
is only encodeable as 5-bytemov r32, imm32
. After putting the absolute address into a register, of coursecall
needs to be absolute. (And that's all x86 has available). I edited your example to comment the instruction lengths. What's missing is a 3-byte encoding forlea r32, [EIP + rel8]
(because there's no such addressing mode, and 32-bit mode doesn't have PC-relative address generation other than call). – Exegeticscall
with a rel32 (instead of an address) in a register would be useful for anything outside of this code-golf problem, and you'd still have to generate the relative offset in a register somehow. – Exegetics