From: Wolfgang Kern on

Rod Pemberton in discussion with Chuck Crayne:

[...]
>> The cpu uses bits 0-2 to enforce the security rules; bit 3
>> to select between the GDT and LDT; and bits 4-15 as an index into the
>> selected table. Under no circumstances does it deal with 8, 16, 32, or
>> 64 bit entities.

> You've just stated the operations of a descriptor... not a selector. A
> selector is just a numerical index, i.e., n*8, n=0,1,2,3..., into the
> descriptor table.

You both are right and wrong :)

The 'Selector' contains:
b15..b3 the index into GDT or LDT (just ANDed, no MUL 8 required)
b2 0=GDT ; 1=LDT
b1,b0 Priviledge-Level 0..3

__
wolfgang



From: Rod Pemberton on

"Wolfgang Kern" <nowhere(a)never.at> wrote in message
news:g9rs5d$mn3$1(a)newsreader2.utanet.at...
>
> Rod Pemberton in discussion with Chuck Crayne:
>
> [...]
> >> The cpu uses bits 0-2 to enforce the security rules; bit 3
> >> to select between the GDT and LDT; and bits 4-15 as an index into the
> >> selected table. Under no circumstances does it deal with 8, 16, 32, or
> >> 64 bit entities.
>
> > You've just stated the operations of a descriptor...

Wrong... to me! Those bits are part of a selector... Sorry, Chuck.


Rod Pemberton



From: Chuck Crayne on
On Fri, 5 Sep 2008 13:32:42 -0400
"Rod Pemberton" <do_not_have(a)nohavenot.cmm> wrote:

> IMO, one has to be slightly perverse, in a non-sexual way, to be a
> tech writer.

I do know something about tech writers, since I have had the
responsibility for approving the performance reviews of a few of them,
and, as in any profession, some are better than others. However, my
comment was not about the technical qualifications of the tech writer,
but rather about the hardware knowledge of the average programmer,
which is the target audience of the manuals which we have been
discussing.

> Why would you gate to or through a hidden
> register when the data is already in a register? It just needs to be
> placed onto the correct data bus at the correct time.

My point, exactly. No "load" is required.

> > Nor does the concept of "default register size" apply to the source
> > register.
>
> Why not? It should apply to to all registers for the mode.

What you call the "default register size" is nothing more that a bit in
the current cs descriptor, which must be tested by the cpu logic for
those parts of an instruction which have both 16 and 32 bit forms. In
the case of the source register for lsl, there is no need to test this
bit, because (as the manual makes quite clear) the cpu always uses 16
bits.

> A
> selector is just a numerical index, i.e., n*8, n=0,1,2,3..., into the
> descriptor table.

I quote (i.e. cut and paste) from the manual:

A segment selector contains the following items:

Index(Bits 3 through 15)
— Selects one of 8192 descriptors in the GDT or LDT.

TI (table indicator) flag (Bit 2)
— Specifies the descriptor table to use

Requested Privilege Level (RPL) (Bits 0 and 1)
— Specifies the privilege level of the selector.

--
Chuck
http://www.pacificsites.com/~ccrayne/charles.html


From: Martin Str|mberg on
Frank Kotler <fbkotler(a)verizon.net> wrote:
> This is true. (Merely out of curiosity, I'd like to see it done on an
> older processor. Doesn't "make sense" to me that it would read 32 bits,
> but maybe... I don't think "must make sense to Frank" is in Intel's
> design criteria... I'd bet on "error in manual"... but I wouldn't bet
> more than I could afford to lose...)

I couldn'�t make you nasm program link, so I made my own DJGPP C
program instead:

#include <stdio.h>
#include <sys/segments.h>
#include <crt0.h>

char **__crt0_glob_function(char *arg) {return 0;}
void __crt0_load_environment_file(char *progname) { }

static unsigned int get_segment_limit_reg( unsigned short s )
{
unsigned int o;
asm( "lsll %%eax, %%eax \n"
: "=a" (o)
: "0" (s)
);

return o;
}

static unsigned short get_segment_limit_mem_size16( unsigned char *p )
{
unsigned short o;
asm( "lslw (%%eax), %%ax \n"
: "=a" (o)
: "0" (p) );

return o;
}

static unsigned int get_segment_limit_mem_size32( unsigned char *p )
{
unsigned int o;
asm( "lsll (%%eax), %%eax \n"
: "=a" (o)
: "0" (p)
);

return o;
}


int main(int argc, char *argv[])
{
unsigned int segment_limit;
unsigned char *p;
unsigned short ds;

ds = _my_ds();
segment_limit = get_segment_limit_reg( ds );
printf("segment 0x%04hx has limit 0x%08x.\n", ds, segment_limit);
fflush(stdout);

p = ((unsigned char *)segment_limit) - 1;
printf("Setting last two bytes in my segment to 0x%04hx\n", ds);
p[0] = ds&0xff;
p[1] = (ds&0xff00)>>16;

printf("Running lslw (0x%08x), %%ax: ", (unsigned int)p);
fflush(stdout);

segment_limit = get_segment_limit_mem_size16( p );
printf("success: 0x%08x.\n", segment_limit);
fflush(stdout);

printf("Running lsll (0x%08x), %%eax: ", (unsigned int)p);
fflush(stdout);

segment_limit = get_segment_limit_mem_size32( p );
printf("success: 0x%08x.\n", segment_limit);
fflush(stdout);

if( argc < 2 )
{
printf("Skipping movl (0x%08x), %%eax test.\n", (unsigned int)p);
}
else
{
unsigned int v = 0;

printf("Running movl (0x%08x), %%eax: ", (unsigned int)p);
fflush(stdout);

asm( "mov (%%eax), %%eax \n"
: "=a" (v)
: "0" (p)
);

printf(" success: 0x%08x.\n", v);
fflush(stdout);
}

return 0;
}

It does not crash on any lsl instruction. But on the mov (%eax), %eax
it does. On an AMD Athlon, on a Pentium ~100MHz and on a 386.


--
MartinS
From: Rod Pemberton on

"Chuck Crayne" <ccrayne(a)crayne.org> wrote in message
news:20080905152743.0cc0e2e3(a)thor.crayne.org...
On Fri, 5 Sep 2008 13:32:42 -0400
"Rod Pemberton" <do_not_have(a)nohavenot.cmm> wrote:

> > > Nor does the concept of "default register size" apply to the source
> > > register.
> >
> > Why not? It should apply to to all registers for the mode.
>
> What you call the "default register size" is nothing more that a bit in
> the current cs descriptor, which must be tested by the cpu logic for
> those parts of an instruction which have both 16 and 32 bit forms. In
> the case of the source register for lsl, there is no need to test this
> bit, because (as the manual makes quite clear) the cpu always uses 16
> bits.

While there is no need to test the bit, not doing so requires extra logic be
implemented for just a few instructions. Why would they use more
gates/logic just to force 16-bits onto the bus for a few instructions,
instead of just placing the size selected by the descriptor (and overrides)
onto the bus? I.e., they'd have to implement logic to hardcode an implicit
and non-overridable size override for 32-bit mode. I can't see why they'd
waste gates on this when a simpler more generic solution works.

> > A
> > selector is just a numerical index, i.e., n*8, n=0,1,2,3..., into the
> > descriptor table.
>
> I quote (i.e. cut and paste) from the manual:
>

Yes, I said sorry to you in the reply to HK. I haven't used the lower bits
in my OS. And, it seems that while I read the descriptor section
thoroughly some time ago, I ignored the selector section for some unknown
reason...


Rod Pemberton