4

How do I perform an indirect far jump/call in protected mode? First I was thinking that doing this is allowable:

jmp 0x10:eax;

(Don't worry about the segment selector..the 2nd entry of my GDT is a valid code segment)

But when nasm assembled it, it was a syntax error. Looking at the Book 2a of the Intel (instruction set reference) manual, it can only be done using jmp ptr16:32, where the ptr16:32 is an immediate value, or using jmp m16:32, where the m16:32 is a memory location containing the 48-bit jump address (the 16:32).

Now I tried to encode it this way:

mov dword[ds:jumpaddress_offset],eax
; or just dword[jumpaddress_offset],eax
mov word[ds:jumpaddress_sel],0x10;
; or just mov word[ds:jumpaddress_sel],0x10;
jmp dword far [dword ds:jumpaddress];
...
jumpaddress:
jumpaddress_sel dw 0
jumpaddress_offset dd 0

It assembled successfully, but when I tried to run it the processor gets a general protection fault and restarts. I don't know what happened.

I assumed the encoding is like this:

(for example I want to jump to 0x10:0x8010 using indirect jump)

dw 0x10
dd 0x8010

What could be the wrong with this? Is it that the 48-bit memory value should be coded in little endian? And should it be coded like this?

;0010 0000 8010
dd 0x10,0x80,0,0,0x10,0

I haven't tried doing the last one.

Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
prinzrainer
  • 319
  • 1
  • 6
  • 12
  • Related, same thing in 16-bit mode: [NASM far jump / far call in real mode and ASM code conventions](https://stackoverflow.com/q/15247774) . Also [Jumping to a far address in real mode](https://stackoverflow.com/q/31944041) – Peter Cordes Oct 24 '22 at 16:48

2 Answers2

5

A frequently used trick is to emulate the jump using a far ret, such as:

push 0x10
push eax
retf
Jester
  • 56,577
  • 4
  • 81
  • 125
  • 1
    I've already solved it. The 48-bit address should be coded in little endian, that is define the 32-bit offset first and then the 16-bit segment selector.. Well, as you can do the trick, there are also some advantages of using the indirect jump. – prinzrainer Jan 29 '11 at 02:48
1

The x86 processors use little-endian mode. In keeping with that, the offset of a target precedes the segment in memory. For your example you should use:

dd 0x8010 ;offset of far jump

dd 0x10 ;segment of far jump, expanded to double-word for alignment reasons

;------------------

db 0x10, 0x80, 0, 0, 0x10, 0, 0, 0 ;will also work.

You might still get a privilege exception. For the code to work the target code segment must have the same privilege level as the source segment.

Primary source: The Processor and Coprocessor by Robert L. Hummel

Pvblivs
  • 11
  • 1