jmp far [jump_value]
jump_value:
dq some_addr
dw CODE_SELECTOR
don't work
The biggest problem with that code is architectural. The original AMD64 instruction set did not support/encode JMP FAR MEM16:64, therefore it is not universal and such code should be avoided.
The following code is three different ways that
should put the processor into compatibility mode. It assumes that
COMPAT_SEL is a valid (protected mode code, IIRC) GDT selector. Operative word being
should, as my working knowledge is a bit rusty and some minor changes may be needed.
Also note that
o64 retf should probably be its own instruction called
retfq, akin to
iretq. It was probably overlooked due to imprecise instruction set documentation. However,
%define retfq o64 retf should suffice in the interim.
[BITS 64]
%define retfq o64 retf
%define COMPAT_SEL 8 ;Compatibility Mode GDT Selector (change as needed)
;Indirect 32-bit Far Jump Version
jmp far DWORD[ptr] ;JMP FAR MEM16:32 (works on all x86-64 processors)
ptr:
DD COMPAT_START ;EIP of Compatibility Mode Entrypoint
DW COMPAT_SEL ;Compatibility Mode GDT Selector
;RETFQ Version
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
retfq ;64-bit RETF
;IRETQ Version
mov rbx,rsp ;Current Stack Pointer
mov ax,ss ;Segment Selector
movzx eax,ax ;Zero Extend top 48-bits of RAX
push rax ;Push QWORD Aligned SS
push rbx ;Push Desired Stack Pointer
pushfq ;Push RFLAGS
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
iretq ;Return from Long Mode Interrupt
[BITS 32]
;Compatibility Mode Entrypoint
COMPAT_START:
jmp $
HtH.