This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
.code16gcc, i386, and loop/jcc/jmp data-size overrides
- From: "No Name" <no_mayl at hotmail dot com>
- To: binutils at sources dot redhat dot com
- Date: Fri, 07 Apr 2006 16:39:17 -0700
- Subject: .code16gcc, i386, and loop/jcc/jmp data-size overrides
- Bcc:
Would it be ok for gas to generate extra size prefixes when compiling with
code16gcc?
Like that the produced object with 16bit code could run with an EIP >
0xffff.
It would seem that the spirit of code16gcc is to be 32bit allover anyway.
The attached patch is probably incomplete, "jcxz" should be tweaked also.
And maybe the "loop/jcxz" handling is trickier due to suffixes manipulating
addr-sizes instead of the data-sizes.
* code
.L19:
movl -8(%ebp), %eax
addl 8(%ebp), %eax
cmpb $0, (%eax)
jne .L21
!!>> jmp .L20 <<!!
.L21:
* original gnu assembler
After reloc to 0x40000, executing the jmp cause eip to be truncated to 16bit
(data size).
67 66 8b 45 f8 addr32 mov 0xfffffff8(%ebp),%eax
67 66 03 45 08 addr32 add 0x8(%ebp),%eax
67 80 38 00 addr32 cmpb $0x0,(%eax)
75 03 jne 40250 <printf+0x2f>
!!>> e9 68 01 jmp 3b8 <SEL_GDT_USER3+0x328> <<!!
67 66 8b 45 f8 addr32 mov 0xfffffff8(%ebp),%eax
67 66 03 45 08 addr32 add 0x8(%ebp),%eax
* with the attached binutils 1.16 patch
67 66 8b 45 f8 addr32 mov 0xfffffff8(%ebp),%eax
67 66 03 45 08 addr32 add 0x8(%ebp),%eax
67 80 38 00 addr32 cmpb $0x0,(%eax)
66 data32
75 06 jne 40262 <printf+0x33>
!!>> 66 e9 8a 01 00 00 jmpl 403ec <printf+0x1bd> <<!!
67 66 8b 45 f8 addr32 mov 0xfffffff8(%ebp),%eax
67 66 03 45 08 addr32 add 0x8(%ebp),%eax
--
jpa
diff -ur binutils-2.16/gas/config/tc-i386.c binutils-2.16-code16gccFix/gas/config/tc-i386.c
--- binutils-2.16/gas/config/tc-i386.c 2005-04-13 10:58:42.000000000 -0700
+++ binutils-2.16-code16gccFix/gas/config/tc-i386.c 2006-04-07 16:19:58.000000000 -0700
@@ -2446,10 +2446,15 @@
unsigned int prefix = DATA_PREFIX_OPCODE;
if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
- prefix = ADDR_PREFIX_OPCODE;
+ {
+ if (!add_prefix (prefix))
+ return 0;
+ prefix = ADDR_PREFIX_OPCODE;
+ }
if (!add_prefix (prefix))
return 0;
+
}
/* Set mode64 for an operand. */
@@ -3179,6 +3184,13 @@
FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
i.prefixes -= 1;
}
+ if (flag_code == CODE_16BIT)
+ if (i.prefix[DATA_PREFIX] != 0)
+ {
+ FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
+ i.prefixes -= 1;
+ }
+
/* Pentium4 branch hints. */
if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
|| i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
diff -ur binutils-2.16/include/opcode/i386.h binutils-2.16-code16gccFix/include/opcode/i386.h
--- binutils-2.16/include/opcode/i386.h 2005-04-13 10:59:03.000000000 -0700
+++ binutils-2.16-code16gccFix/include/opcode/i386.h 2006-04-07 16:10:34.000000000 -0700
@@ -393,15 +393,15 @@
{"lcall", 1, 0xff, 3, 0, wl_Suf|Modrm|DefaultSize, {WordMem|JumpAbsolute, 0, 0} },
#define JUMP_PC_RELATIVE 0xeb
-{"jmp", 1, 0xeb, X, 0, NoSuf|Jump, { Disp,0, 0} },
-{"jmp", 1, 0xff, 4, CpuNo64, wl_Suf|Modrm, { WordReg|WordMem|JumpAbsolute, 0, 0} },
-{"jmp", 1, 0xff, 4, Cpu64, wq_Suf|Modrm|NoRex64, { Reg16|Reg64|ShortMem|LLongMem|JumpAbsolute, 0, 0} },
+{"jmp", 1, 0xeb, X, 0, NoSuf|Jump|DefaultSize, { Disp,0, 0} },
+{"jmp", 1, 0xff, 4, CpuNo64, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem|JumpAbsolute, 0, 0} },
+{"jmp", 1, 0xff, 4, Cpu64, wq_Suf|Modrm|NoRex64|DefaultSize, { Reg16|Reg64|ShortMem|LLongMem|JumpAbsolute, 0, 0} },
/* Intel Syntax. */
-{"jmp", 2, 0xea, X, CpuNo64,wl_Suf|JumpInterSegment, { Imm16, Imm16|Imm32, 0} },
+{"jmp", 2, 0xea, X, CpuNo64,wl_Suf|JumpInterSegment|DefaultSize, { Imm16, Imm16|Imm32, 0} },
/* Intel Syntax. */
-{"jmp", 1, 0xff, 5, 0, x_Suf|Modrm, { WordMem|JumpAbsolute, 0, 0} },
-{"ljmp", 2, 0xea, X, CpuNo64, wl_Suf|JumpInterSegment, { Imm16, Imm16|Imm32, 0} },
-{"ljmp", 1, 0xff, 5, 0, wl_Suf|Modrm, { WordMem|JumpAbsolute, 0, 0} },
+{"jmp", 1, 0xff, 5, 0, x_Suf|Modrm|DefaultSize, { WordMem|JumpAbsolute, 0, 0} },
+{"ljmp", 2, 0xea, X, CpuNo64, wl_Suf|JumpInterSegment|DefaultSize, { Imm16, Imm16|Imm32, 0} },
+{"ljmp", 1, 0xff, 5, 0, wl_Suf|Modrm|DefaultSize, { WordMem|JumpAbsolute, 0, 0} },
{"ret", 0, 0xc3, X, CpuNo64,wl_Suf|DefaultSize, { 0, 0, 0} },
{"ret", 1, 0xc2, X, CpuNo64,wl_Suf|DefaultSize, { Imm16, 0, 0} },
@@ -415,36 +415,36 @@
{"leave", 0, 0xc9, X, Cpu64, wq_Suf|DefaultSize|NoRex64, { 0, 0, 0} },
/* Conditional jumps. */
-{"jo", 1, 0x70, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jno", 1, 0x71, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jb", 1, 0x72, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jc", 1, 0x72, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnae", 1, 0x72, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnb", 1, 0x73, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnc", 1, 0x73, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jae", 1, 0x73, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"je", 1, 0x74, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jz", 1, 0x74, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jne", 1, 0x75, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnz", 1, 0x75, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jbe", 1, 0x76, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jna", 1, 0x76, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnbe", 1, 0x77, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"ja", 1, 0x77, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"js", 1, 0x78, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jns", 1, 0x79, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jp", 1, 0x7a, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jpe", 1, 0x7a, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnp", 1, 0x7b, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jpo", 1, 0x7b, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jl", 1, 0x7c, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnge", 1, 0x7c, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnl", 1, 0x7d, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jge", 1, 0x7d, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jle", 1, 0x7e, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jng", 1, 0x7e, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jnle", 1, 0x7f, X, 0, NoSuf|Jump, { Disp, 0, 0} },
-{"jg", 1, 0x7f, X, 0, NoSuf|Jump, { Disp, 0, 0} },
+{"jo", 1, 0x70, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jno", 1, 0x71, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jb", 1, 0x72, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jc", 1, 0x72, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnae", 1, 0x72, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnb", 1, 0x73, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnc", 1, 0x73, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jae", 1, 0x73, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"je", 1, 0x74, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jz", 1, 0x74, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jne", 1, 0x75, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnz", 1, 0x75, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jbe", 1, 0x76, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jna", 1, 0x76, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnbe", 1, 0x77, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"ja", 1, 0x77, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"js", 1, 0x78, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jns", 1, 0x79, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jp", 1, 0x7a, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jpe", 1, 0x7a, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnp", 1, 0x7b, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jpo", 1, 0x7b, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jl", 1, 0x7c, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnge", 1, 0x7c, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnl", 1, 0x7d, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jge", 1, 0x7d, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jle", 1, 0x7e, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jng", 1, 0x7e, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jnle", 1, 0x7f, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
+{"jg", 1, 0x7f, X, 0, NoSuf|Jump|DefaultSize, { Disp, 0, 0} },
/* jcxz vs. jecxz is chosen on the basis of the address size prefix. */
{"jcxz", 1, 0xe3, X, CpuNo64,NoSuf|JumpByte|Size16, { Disp, 0, 0} },
@@ -456,16 +456,16 @@
%cx rather than %ecx for the loop count, so the `w' form of these
instructions emit an address size prefix rather than a data size
prefix. */
-{"loop", 1, 0xe2, X, CpuNo64,wl_Suf|JumpByte,{ Disp, 0, 0} },
+{"loop", 1, 0xe2, X, CpuNo64,wl_Suf|JumpByte|DefaultSize,{ Disp, 0, 0} },
{"loop", 1, 0xe2, X, Cpu64, lq_Suf|JumpByte|NoRex64,{ Disp, 0, 0} },
-{"loopz", 1, 0xe1, X, CpuNo64,wl_Suf|JumpByte,{ Disp, 0, 0} },
+{"loopz", 1, 0xe1, X, CpuNo64,wl_Suf|JumpByte|DefaultSize,{ Disp, 0, 0} },
{"loopz", 1, 0xe1, X, Cpu64, lq_Suf|JumpByte|NoRex64,{ Disp, 0, 0} },
-{"loope", 1, 0xe1, X, CpuNo64,wl_Suf|JumpByte,{ Disp, 0, 0} },
+{"loope", 1, 0xe1, X, CpuNo64,wl_Suf|JumpByte|DefaultSize,{ Disp, 0, 0} },
{"loope", 1, 0xe1, X, Cpu64, lq_Suf|JumpByte|NoRex64,{ Disp, 0, 0} },
-{"loopnz", 1, 0xe0, X, CpuNo64,wl_Suf|JumpByte,{ Disp, 0, 0} },
+{"loopnz", 1, 0xe0, X, CpuNo64,wl_Suf|JumpByte|DefaultSize,{ Disp, 0, 0} },
{"loopnz", 1, 0xe0, X, Cpu64, lq_Suf|JumpByte|NoRex64,{ Disp, 0, 0} },
-{"loopne", 1, 0xe0, X, CpuNo64,wl_Suf|JumpByte,{ Disp, 0, 0} },
+{"loopne", 1, 0xe0, X, CpuNo64,wl_Suf|JumpByte|DefaultSize,{ Disp, 0, 0} },
{"loopne", 1, 0xe0, X, Cpu64, lq_Suf|JumpByte|NoRex64,{ Disp, 0, 0} },
/* Set byte on flag instructions. */