Page 1 of 1

Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 3:23 am
by Haroogan
There are 2 different ways to achieve it. So I'm going to post 2 different snippets respectively:

#1

Code: Select all

BITS 16

%define LinearAddress(SegmentAddress,OffsetAddress) SegmentAddress * 0x10 + OffsetAddress

Code16:
	...
	JMP 8:LinearAddress(BootLoader2.SEGMENT_ADDRESS,Code32)

BITS 32

Code32:
	...
#2

Code: Select all

BITS 16

%define LinearAddress(SegmentAddress,OffsetAddress) SegmentAddress * 0x10 + OffsetAddress
%macro JMP32 2
	DB 0x66
	DB 0xEA
	DD %2;Address
	DW %1;Selector
%endmacro

Code16:
	...
	JMP32 8,LinearAddress(BootLoader2.SEGMENT_ADDRESS,Code32)

BITS 32

Code32:
	...
Both of them work just fine. But I've noticed that the 2nd one occupies more memory. So the 2nd one is really the 32 bit jump and the 1st one is not. But some people still recommend the 1st one and others - the 2nd one. Which one should I choose? And why? What's the essence of their difference?

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 4:10 am
by egos
#2 of course if destination code segment is 32-bit. There is a probability that high word of eip is not equal to zero.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 5:07 am
by Owen
egos wrote:#2 of course if destination code segment is 32-bit. There is a probability that high word of eip is not equal to zero.
Utter junk. Both 32-bit and 64-bit jumps set the full width of EIP

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 5:14 am
by egos
And what about 16-bit jump ;)

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 5:33 am
by Owen
It zeros out the upper bits of rIP. If the upper bits were not zeroed, you would violate the segment limit...

A good assembler will therefore detect when the address will fit in 16-bits and use the 16-bit version of the jump

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 6:11 am
by egos
Owen wrote:It zeros out the upper bits of rIP.
Maybe in emulators but not in real CPUs.
If the upper bits were not zeroed, you would violate the segment limit...
CPU ignores high word of eip while executing 16-bit code therefore an error doesn't occur.
A good assembler will therefore detect when the address will fit in 16-bits and use the 16-bit version of the jump
And this behaviour will be fatal if high word of eip during execution is not equal to zero. To jump from 16-bit code to 32-bit code you should use forced 32-bit far jump anywhere except if you sure that eip.31-16=0 (or if you want to jump to eip.31-16 shl 16 + 16-bit destination offset :D).

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 6:51 am
by Owen
If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared.
This is from the Intel manuals, volume 2A, at time of writing page 3-554.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 8:20 am
by Haroogan
Anyway, I believe #2 is safer and more stable.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 9:48 am
by egos
Owen wrote:
If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared.
This is from the Intel manuals, volume 2A, at time of writing page 3-554.
Good argument but you didn't take into account that some people make CPUs and another write manuals for them. Also I can assume that behaviour of CPUs can change from one model to another. I tested some Pentium processors and they worked precisely as I said above.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 11:22 am
by Owen
egos wrote:
This is from the Intel manuals, volume 2A, at time of writing page 3-554.
Good argument but you didn't take into account that some people make CPUs and another write manuals for them. Also I can assume that behaviour of CPUs can change from one model to another. I tested some Pentium processors and they worked precisely as I said above.
The behavior of the instruction is architecturally defined. It cannot change from one processor model to another. Can you cite a reference on a processor having the bug you mentioned? I fail to believe that such a bug would not be documented anywhere on the internet, particularly when the Pentium dates back to the days of segmented software. I certainly can't find it in Intel's Pentium errata sheet.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 12:52 pm
by egos
It was long time ago when I used 16-bit far jump to enter PM and recommended to other people to do so :oops:

Code: Select all

; fasm syntax
  if Startup32<10000h
  jmp KCODE:Startup32
  else
  jmp fword KCODE:Startup32
  end if
When I saw what happened when eip.31-16 != 0 on my testing computer (probably it was same one that I have now) I was shocked :shock: Now I have Intel Pentium MMX for testing. We can write testing code here and then test old and modern (I have Intel Core2 Quad Q9300 and Intel i7 920 at home too) CPUs with it.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 12:59 pm
by xenos
I guess you really disliked that 32 bit jump when you wrote "fword" instead of "dword"...

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 1:05 pm
by egos
In fasm syntax fword (or pword) means six-byte pointer. "dword" in this case (in 16-bit code) is default and means four-byte pointer.

Re: Details of the Far JMP into Protected Mode

Posted: Fri Aug 12, 2011 2:01 pm
by xenos
Ah, sorry, you're right - I haven't used fasm for a very long time... I was thinking about something like "ljmpl" in GNU as syntax, or the even more similar "jmp dword Seg:Off" in NASM syntax...