Bug 10740 - Intel syntax far jumps broken
Summary: Intel syntax far jumps broken
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.21
: P2 normal
Target Milestone: ---
Assignee: unassigned
Depends on:
Reported: 2009-10-06 13:59 UTC by Thorsten Glaser
Modified: 2014-05-28 19:41 UTC (History)
2 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Last reconfirmed:

A patch (648 bytes, patch)
2009-10-12 23:18 UTC, H.J. Lu
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thorsten Glaser 2009-10-06 13:59:27 UTC
Forwarding http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=541535

First, I show that this can be reproduced with binutils-current checked
out from AnonCVS on 2009-10-06 on approximately 13:30 UTC, then I will
copy and paste the original problem report I submitted to Debian after
this issue (with an assembly file of mine) was reported to me by Mika
“grml.org” Prokop. My thoughts on this: congratulations on trying to
make the Intel syntax more Intel style (ljmp → JMP FAR), but you’re a
decade (at the least) too late and are breaking a large existing codebase.
Maybe 「.intel_syntax noprefix,v=2」 style versioning should be used?

tglase@tglase:~ $ ~/stuff/binutils-current/bin/as -V
GNU assembler version 2.20.51 (i686-pc-linux-gnu) using BFD version (GNU 

tglase@tglase:~ $ ~/stuff/binutils-current/bin/as -o x.o testmin.s
testmin.s: Assembler messages:
testmin.s:5: Error: too many memory references for `ljmp'
1|tglase@tglase:~ $ ~/stuff/binutils-current/bin/as -o x.o testmin2.s
testmin2.s: Assembler messages:
testmin2.s:5: Error: junk `0xF000:0xFFF0' after expression

Package: binutils                                                                                           
Severity: normal                                                                                            
First of, a totally reduced minimal testcase. Let's try it on MirBSD:                                       
tg@herc:~ $ cat >testmin.s                                                                                  
        .intel_syntax noprefix                                                                              
        .globl  _start                                                                                      
_start: ljmp    0xF000,0xFFF0                                                                               
tg@herc:~ $ cc -nostdlib -Wl,--oformat,binary -Wl,-Ttext,0 testmin.s                                        
tg@herc:~ $ hd a.out                                                                                        
00000000  EA F0 FF 00 F0          -                          |.....|                                        
tg@herc:~ $ as -V                                                                                           
GNU assembler version 050707 () using BFD version 050707 20050707                                           
This is an i386 native GNU as, targetting (here) i8086 (due to the .code16                                  
pseudo-op) and using Intel syntax, as opposed to that cruel AT&T syntax,                                    
which thankfully has been supported by about every i386 gas from 1999 and                                   

It fails on Debian sid though (both amd64 and i386, I only have an i386                                     
sid schroot though):                                                                                        
tg@frozenfish:~ $ as testmin.s                                                                              
testmin.s: Assembler messages:                                                                              
testmin.s:5: Error: too many memory references for jmp'                                                     
1|tg@frozenfish:~ $ as -V                                                                                   
GNU assembler version 2.19.51 (i486-linux-gnu) using BFD version (GNU Binutils 
for Debian) 
Oh how great. Let's try the i386 lenny schroot.                                                             
tg@frozenfish:~ $ as testmin.s                                                                              
tg@frozenfish:~ $ file a.out                                                                                
a.out: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped                              
tg@frozenfish:~ $ objdump -d -Mintel,i8086 a.out                                                            
a.out:     file format elf32-i386                                                                           
Disassembly of section .text:                                                                               
00000000 <_start>:                                                                                          
   0:   ea f0 ff 00 f0          jmp    0xf000:0xfff0                                                        
tg@frozenfish:~ $ as -V                                                                                     
GNU assembler version 2.18.0 (i486-linux-gnu) using BFD version (GNU Binutils 
for Debian)   
Cool, it works there... (objdump on BSD shows s/:/,/ otherwise the same)                                    

Now I install binutils-doc and "info as", then I read that the syntax for                                   
far jumps has changed. Ye gods, how am I supposed to distinguish between                                    
these when I target gas' intel syntax? But other than that issue, which                                     
is VERY annoying and should be reverted upstream (i.e. the "older" syntax                                   
should still be accepted), it simply doesn't work!                                                          
   * Immediate form long jumps and calls are call/ljmp $SECTION,                                            
     $OFFSET' in AT&T syntax; the Intel syntax is all/jmp far                                               
     SECTION:OFFSET'.  Also, the far return instruction is ret                                              
     $STACK-ADJUST' in AT&T syntax; Intel syntax is et far                                                  
(Intersting side note, the older syntax matched AT&T more closely; this                                     
seems to be a try to get it more close to other Intel syntax assemblers,                                    
which per se isn't a bad thing - or would have been in 1999. Now it's too                                   
late... especially since more recent binutils are GPLv3.)                                                   
tg@frozenfish:~ $ cat testmin2.s                                                                            
        .intel_syntax noprefix                                                                              
        .globl  _start                                                                                      
_start: jmp far 0xF000:0xFFF0                                                                               
tg@frozenfish:~ $ as testmin2.s                                                                             
testmin2.s: Assembler messages:                                                                             
testmin2.s:5: Error: junk F000:0xFFF0' after expression                                                     

So there isn't even a way to do a JMP FAR here. (Apologies if my editor                                     
stripped U+0060 while pasting, it's a command character and shouldn't                                       
be used in any strings ever. Ask Markus Kuhn...)                                                            
I invoke the "I didn't do anything! (I didn't even do anything before!)"                                    
because the aforementioned assembly source compiles fine using other ver-                                   
sions of gas. I would like to get this fixed, as grml depends on it; it                                     
may or may not be a bug you'd want to forward upstream.
Comment 1 H.J. Lu 2009-10-07 19:42:49 UTC
I have a hard time to understand what the problem is.
Please provide

1. Assembly source.
2. Command line options.
3. Expected output.
Comment 2 Thorsten Glaser 2009-10-10 20:36:54 UTC
> 1. Assembly source.

        .intel_syntax noprefix
        .globl  _start
_start: ljmp    0xF000,0xFFF0

> 2. Command line options.

tg@bleu:~ $ as -o x.o x.s

> 3. Expected output.

tg@bleu:~ $ objdump -D -Mintel,i8086 x.o

x.o:     file format elf32-i386

Disassembly of section .text:

00000000 <_start>:
   0:   ea f0 ff 00 f0          jmp    0xf000,0xfff0
Comment 3 H.J. Lu 2009-10-10 21:35:23 UTC
(In reply to comment #2)
> > 1. Assembly source.
>         .intel_syntax noprefix
>         .text
>         .code16
>         .globl  _start
> _start: ljmp    0xF000,0xFFF0

Are there anything else which no long work? How about lcall?
Comment 4 H.J. Lu 2009-10-12 23:18:59 UTC
Created attachment 4275 [details]
A patch
Comment 5 cvs-commit@gcc.gnu.org 2009-10-13 16:23:40 UTC
Subject: Bug 10740

CVSROOT:	/cvs/src
Module name:	src
Changes by:	hjl@sourceware.org	2009-10-13 16:23:25

Modified files:
	gas            : ChangeLog 
	gas/config     : tc-i386-intel.c tc-i386.c 
	gas/testsuite  : ChangeLog 
	gas/testsuite/gas/i386: jump.d jump.s jump16.d jump16.s 

Log message:
	2009-10-13  H.J. Lu  <hongjiu.lu@intel.com>
	PR gas/10740
	* config/tc-i386-intel.c (i386_intel_operand): Handle call
	and jump with 2 immediate operands.
	* config/tc-i386.c (i386_finalize_immediate): Don't generate
	error message if operand string is NULL.
	2009-10-13  H.J. Lu  <hongjiu.lu@intel.com>
	PR gas/10740
	* gas/i386/jump.s: Add new tests.
	* gas/i386/jump16.s: Likewise.
	* gas/i386/jump.d: Updated.
	* gas/i386/jump16.d: Likewise.


Comment 6 H.J. Lu 2009-10-13 16:23:58 UTC
Comment 7 Thorsten Glaser 2010-01-03 16:44:05 UTC
I think there may be a documentation or bug issue left:

You are testing for:

	ljmp	0x9090,0x90909090
	ljmp	0x9090:0x90909090
	jmp	0x9090,0x90909090
	jmp	0x9090:0x90909090

The correct writing however is:

	ljmp	$0x9090,$0x90909090

Intel old (which is what I use, since I *must* support older as):
	ljmp	0x9090,0x90909090

Intel new (which is used by other Intel assemblers):
	jmp far	0x9090:0x90909090

The latter is also backed by the documentation.

However, thanks for fixing my original issue. The fix is
already in Debian experimental, so this is just for con-
sistency and so that other people don’t stumble upon it.

My proposed least-intrusive fix is:
when 'jmp far' is encountered, check if we have indeed
both a segment and offset following, if yes handle it as
'ljmp', if not error out. (This may basically make 'jmp
far' a new opcode.)
Comment 8 Jackie Rosen 2014-02-16 16:56:52 UTC Comment hidden (spam)