Bug 89487 - ljmp *%eax can't be created
ljmp *%eax can't be created
Status: CLOSED NOTABUG
Product: Red Hat Linux
Classification: Retired
Component: binutils (Show other bugs)
7.1
i386 Linux
low Severity low
: ---
: ---
Assigned To: Jakub Jelinek
Brian Brock
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2003-04-23 09:54 EDT by Gregg Mattinson
Modified: 2005-10-31 17:00 EST (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2003-04-24 11:32:20 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Gregg Mattinson 2003-04-23 09:54:11 EDT
Description of problem:
A far jump to an indirect address can not be created using __asm __volatile
statements.
According to Intel docs, this should produce the instruction sequence FF /5, but
instead I get the error "suffix or operands invalid for `ljmp'"

Version-Release number of selected component (if applicable):
gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)


How reproduce:
Create a .c file, and in main() place:
    __asm __volatile("ljmp *%eax");
A compiler error will result.  However, the following works:
    __asm __volatile("jmp *%eax");
But, as expected, this produces a near jump.

If I hack the correct machine code into my binary, then objdump -d disassembles
it correctly.  The only change needed is to support ljmp with an indirect
address.  Here is the correct machine code which should result:

ljmp *%eax  -> 0xFF 0xE8
jmp  *%eax  -> 0xFF 0xE0

So, the only difference is setting the 3rd bit of the second opcode.

As a work around, I have placed the following in my code:
            __asm __volatile(".byte 0xFF");
            __asm __volatile(".byte 0xE8");

Because of this work around, I have placed the bug at low priority.

Thanks,
Gregg
Comment 1 Jakub Jelinek 2003-04-24 05:53:52 EDT
This has nothing to do with gcc.
It is gas which refuses to assemble it.
Now, although it is possible to create .byte 0xff, 0xe8 instruction by hand,
I'd like to know what do you expect the instruction to do and whether any CPU
actually implements it (and how).
You certainly cannot fit a 48 bit destination address into 32 bit register,
if you want to jump to the 48 bit address pointed by %eax register, the insn
is ljmp *(%eax) (which is 0xff 0x28).
Looking e.g. at the bochs IA-32 emulator, 0xff 0xe8 insn generates an invalid
insn exception.
Comment 2 Gregg Mattinson 2003-04-24 11:32:20 EDT
Thanks for pointing out the correct instruction I wanted.  I did not notice the
small difference between the two.

I have changed my code to use ljmp *(%eax) and that appears to work the same as
my old 0xFF 0xE8 hack.

I am running my code in VMware Workstation 3.2.0, so I guess the bug is really
in their code, because they implemented the 0xFF 0xE8 instruction by mistake.

Note You need to log in before you can comment on or make changes to this bug.