On 21/02/2022 14:30, wolfgang kern wrote:
> On 21/02/2022 13:13, James Harris wrote:
>
>>>>> BUT how about
>>>>> PM32:
>>>>> 8B 44 24 fc mov eax.[esp-04] ;SP or ESP depending on seg-size ?
>>>>> RM:
>>>>> 67 8B 44 24 fc mov ax,[esp-04] ;could have an UnReal flat big stack
>
>>>> How do you interpret those?
>>> my disassembler do this for me.
>> :) I was asking what you thought they meant (in the context of
>> different descriptor settings).
>
>> I've been looking in to this a bit more and will have a go at it. See
>> if you think I've got it right or not.
>
> can't give you an A here ...
> both of my and your example instructions use SS by default.
You are right about using SS. Since the earlier post I've found in the
Intel manual under Default Segment Selection Rules the text for uses of
SS and it mentions ESP as well as EBP: "Any memory reference which uses
the ESP or EBP register as a base register." I'd missed off ESP. I will
correct my comments, below, though please don't get diverted by that
because the selection of base register is a side issue compared with the
significance(s) of the D/B bit.
I should say that IME assemblers have no directives for RM or PM32 but
only for "16-bit" and "32-bit" and AISI they are correct in that because
for both of the 16-bit modes (RM and PM16) the instruction encodings are
identical.
Therefore, AISI your second example (which you labelled "RM") cannot
really be RM as it refers to ESP so I presume you mean PM16 (which uses
16-bit encodings but can refer to 32-bit registers).
BTW, to be clear, you referred to /my/ examples but I just copied yours
so there are only two examples, not four.
>
>> Your first example:
>> PM32:
>> 8B 44 24 fc mov eax.[esp-04] ;SP or ESP depending on seg-size ?
>> AIUI:
>> * that will NOT use the SS segment's 'B' bit (which selects SP or ESP
>> but does so only for /implicit/ references to the stack)
I stand by that part of the assessment (until told otherwise!). The B
bit is only used for implicit stack operations and is ignored for
explicit ones.
>
>> * it will use the CS segment's D bit being set to 1 in two ways:
>> 1) it will have adsiz as 32-bit so recognising ESP rather than SP
>> 2) it will have opsiz as 32-bit so recognising EAX rather than AX
I stand by that, too.
>
>> * the accessible range will depend on DS.limit, not SS.limit
>>
>> * it will access ESP relative to DS.base, not relative to SS.base -
>> which could be a source of significant confusion if they don't match.
>
> My SS use a PM16 data-descriptor and my DS a Flat PM32 one.
> No confusion detected :)
Agreed. If MOV EAX,[ESP - 4] uses ESP as a base register then it /will/
use SS.limit and SS.base - although for that instruction the CPU will
still ignore SS.B. Agreed?
>
>> Your second example:
>> RM:
>> 67 8B 44 24 fc mov ax,[esp-04] ;could have an UnReal flat big stack
>
>> * again, won't use anything about the SS segment
>> * will use CS.D=0 to recognise AX
>
> yeah, RM uses 16 bit for AX by default, but 67 allow SIB (uses SS)
Agreed.
>
>> * will use CS.D=0 and adsiz to recognise ESP
>
> there aren't any [SP] addressing modes in RM nor in PM except
> PUSH/POP/CALL/RET.
>
>> * addressable range will depend on DS.limit, not SS.limit
>> * linear address will depend on DS.base, not SS.base.
>
> this is wrong!
Agreed. Issue as above. SS.limit and SS.base will be used.
>
>> Note that it appears that the Big bit on DS (i.e. DS.B) is ignored
>> even though the instructions access DS. Also, the base and limit and
>> everything else from SS are ignored for those instructions.
>
>> The findings may be unexpected (they certainly surprised me) but see
>> the section entitled Segment Descriptors in CHAPTER 3 of
>> PROTECTED-MODE MEMORY MANAGEMENT in Intel manuals.
>
> such false statements are really printed in Intel docs ?
No, what Intel says is as follows. Remember this is about the B bit (aka
D bit on a code seg) which is supposed to be 0 for 16-bit and 1 for
32-bit operation - and which I think we disagree.
D/B (default operation size/default stack pointer size and/or upper
bound) flag
Performs different functions depending on whether the segment descriptor
is an executable code segment, an expand-down data segment, or a stack
segment. (This flag should always be set to 1 for 32-bit code and data
segments and to 0 for 16-bit code and data segments.)
• Executable code segment. The flag is called the D flag and it
indicates the default length for effective addresses and operands
referenced by instructions in the segment. If the flag is set, 32-bit
addresses and 32-bit or 8-bit operands are assumed; if it is clear,
16-bit addresses and 16-bit or 8-bit operands are assumed. The
instruction prefix 66H can be used to select an operand size other than
the default, and the prefix 67H can be used select an address size other
than the default.
• Stack segment (data segment pointed to by the SS register). The flag
is called the B (big) flag and it specifies the size of the stack
pointer used for implicit stack operations (such as pushes, pops, and
calls). If the flag is set, a 32-bit stack pointer is used, which is
stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack
pointer is used, which is stored in the 16-bit SP register. If the stack
segment is set up to be an expand-down data segment (described in the
next paragraph), the B flag also specifies the upper bound of the stack
segment.
• Expand-down data segment. The flag is called the B flag and it
specifies the upper bound of the segment. If the flag is set, the upper
bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is
FFFFH (64 KBytes).
That's all the Intel docs say in that section about the D/B flag. Some
points of note:
* The bit is in the last 16 bits of a descriptor so will be zero for
PM16 for which all those bits are expected to be zero.
* Although Intel say the bit should be set to 1 on all 32-bit segments,
according to the description Intel gives, above, the CPU doesn't check
the bit on any data segments other than SS.
* Even on the stack segment the bit still doesn't influence address size
or operand size of any explicit references to that segment.
IOW even if the B bit were to be clear on DS, ES etc you could still
access them as normal as 32-bit segments.
Going a little further, the B bit is distinct from the G (granularity)
bit so you could define a limit in terms of 4k chunks and access all 4G
with the B bit still being zero.
Surprised? I was.
>>>> BTW, what happens when referring to BP or EBP as in
>>>>
>>>> mov eax, [ebp + 4]
>>>> sub ebp, 8
>>>>
>>>> Does such code use the SS descriptor's B bit?
>
>>> Yes, at least on CPUs which still support the B bit.
>
>> Any advance on "Yes"? :) As above, the Segment Descriptors section of
>> the Intel manual suggests otherwise.
I stand by that, too. For the reasons mentioned above it seems that your
MOV-SUB pair would _not_ take any notice of the SS.B bit.
As ever, further corrections welcome. :)
--
James Harris