i386/x86_64 segment register issuses

Ross Ridge rridge@csclub.uwaterloo.ca
Thu Mar 31 10:23:00 GMT 2005


>A "movw" has a 0x66 prefix. The assembler agree with me. Plain logic
>agrees with me. Being consistent _also_ agrees with me (it's the same
>damn instruction to move to a register, for chrissake!)

When "mov" instruction has both a memory and segment operand the operand
size prefix has no effect.  There is no 32-bit operand size version of
this instruction to switch to or from.

>"movw" is totally different from "movl". They _act_ the same, but that's 
>like saying that "orw $5,%ax" is the same as "orl $5,%eax". They also 
>_act_ the same, but that IN NO WAY makes them the same.

The "orw" and "orl" examples you give are not architecturally equivilent.
They will set EFLAGS differently based on the value the EAX register had
before.  There can also be significant performance difference between
the two instructions because of partial register accesses the "orw"
instruction performs.  Whether "orw" or "orl" would be faster depends on
the processor used and context it's used in.  However, in the case of a
"mov" instruction that has both a segment register and a memory operand
encoding the instruction the presence or absense of operand size prefix
makes absolutely no difference architecturally.  The memory operand
is always 16-bits and only 16-bits of memory is read or written by the
instruction.  The only effect of using a unnecessary operand prefix is to
make the instruction one byte larger and slower to decode.  Unlike your in
"or" example, adding the unneccessary operand size prefix always loses.

A correctly implemented IA-32 assembler should never generate an operand
size prefix for a move instruction between a segment register and a
memory operand.  Doing so would be as pointless as generating unecessary
DS segment overrides on instructions whose memory operands already assume
the DS segment.

>The fact is, if users use "movl" and "movw" explicitly (and the kernel has
>traditionally been _very_ careful to use all instruction sizes explicitly,
>partly exactly because gas itself has been very happy-go-lucky about
>them) ...

The bugs that currently exist in kernel show that being "careful" about
using instruction sizes explicitly hasn't helped you when accessing
segment registers in inline assembly.  The following code doesn't do
what you thought it does:

	unsigned fsindex;
        asm volatile("movl %%fs,%0" : "=g" (fsindex));

>... then that is a GOOD THING. It means that the instruction is
>well-defined to somebody who knows the x86 instruction set ...

Whoever wrote the above code didn't know the x86 instruction set well
enough.

						Ross Ridge

-- 
 l/  //	  Ross Ridge -- The Great HTMU
[oo][oo]  rridge@csclub.uwaterloo.ca
-()-/()/  http://www.csclub.uwaterloo.ca/u/rridge/ 
 db  //	  



More information about the Binutils mailing list