|Summary:||Intel syntax far jumps broken|
|Product:||binutils||Reporter:||Thorsten Glaser <tg>|
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 Binutils) 22.214.171.12491006 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 Version: 126.96.36.19990805-1 Severity: normal First of, a totally reduced minimal testcase. Let's try it on MirBSD: tg@herc:~ $ cat >testmin.s .intel_syntax noprefix .text .code16 .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 later. 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) 188.8.131.5290805 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) 184.108.40.20680103 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 STACK-ADJUST'. (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 .text .code16 .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 .text .code16 .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 5 email@example.com 2009-10-13 16:23:40 UTC
Subject: Bug 10740 CVSROOT: /cvs/src Module name: src Changes by: firstname.lastname@example.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: gas/ 2009-10-13 H.J. Lu <email@example.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. gas/testsuite/ 2009-10-13 H.J. Lu <firstname.lastname@example.org> 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. Patches: http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/ChangeLog.diff?cvsroot=src&r1=1.3983&r2=1.3984 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/config/tc-i386-intel.c.diff?cvsroot=src&r1=1.7&r2=1.8 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/config/tc-i386.c.diff?cvsroot=src&r1=1.399&r2=1.400 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1567&r2=1.1568 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/testsuite/gas/i386/jump.d.diff?cvsroot=src&r1=1.8&r2=1.9 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/testsuite/gas/i386/jump.s.diff?cvsroot=src&r1=1.3&r2=1.4 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/testsuite/gas/i386/jump16.d.diff?cvsroot=src&r1=1.5&r2=1.6 http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gas/testsuite/gas/i386/jump16.s.diff?cvsroot=src&r1=1.3&r2=1.4
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: AT&T: 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.)