experchange > asm

Peter Cheung (01-05-19, 06:53 PM)
Hi All
Why adc byte [eax], 0x7 encoded as 0x67801007 ? In intel manual i see:

80 /2 ib ADC r/m8, imm8

thanks
Peter
Rick C. Hodgin (01-05-19, 07:42 PM)
On 1/5/2019 11:53 AM, Peter Cheung wrote:
> Hi All
> Why adc byte [eax], 0x7 encoded as 0x67801007 ? In intel manual i see:
> 80 /2 ib ADC r/m8, imm8


In a 16-bit segment, the 0x67 instruction prefix override tells it
that you are working with a 32-bit address, rather than the default
16-bit size. It would be different if you used ADC [si],7, for
example.

Page 81:
Rod Pemberton (01-06-19, 03:34 AM)
On Sat, 5 Jan 2019 08:53:02 -0800 (PST)
Peter Cheung <mcheung63> wrote:

> Hi All
> Why adc byte [eax], 0x7 encoded as 0x67801007 ?


First, 0x67801007 is not a 32-bit hex value, as you've posted. It's
67801007 which is a hex byte-sequence. That's why there is no 0x-
prefix or -h postfix on the hex byte-sequence. As a hex byte-sequence,
60801007 is:

67 80 10 07
0x67 0x80 0x10 0x07
67h 80h 10h 07h

Second, as a 32-bit hex value, the instruction would be encoded as
0x07108067, as Intel/AMD is little-endian, not big-endian like
Motorola 68000 ... I.e., Intel/AMD stores the LSB (least significant
byte) in the lowest address. The LSB is 0x67 here. In other words,
the bytes flip from the way they are stored in memory versus
larger registers.

8-bit 0x67 0x80 0x10 0x07
16-bit 0x8067 0x0710
32-bit 0x07108067

> Why [is] adc byte [eax], 0x7 encoded as 67801007 ? (corrected)


So, what is 67801007? It depends on which processor mode executes it:

Disassembly as 64-bit code, via Ndisasm -b64 gives:
00000000 67801007 adc byte [eax],0x7

Disassembly as 32-bit code, via Ndisasm -b32 gives:
00000000 67801007 adc byte [bx+si],0x7

Disassembly as 16-bit code, via Ndisasm -b16 gives:
00000000 67801007 adc byte [eax],0x7

> [what does the 0x67 do to the instruction?]


Let's look at it without the 0x67 byte:

Disassembly as 64-bit code, via Ndisasm -b64 gives:
00000000 801007 adc byte [rax],0x7

Disassembly as 32-bit code, via Ndisasm -b32 gives:
00000000 801007 adc byte [eax],0x7

Disassembly as 16-bit code, via Ndisasm -b16 gives:
00000000 801007 adc byte [bx+si],0x7

If you compare the 16-bit here to 32-bit above, you see that it changes
from 16-bit memory addressing to 32-bit memory addressing for 16-bit
code. I.e., switches address modes.

If you compare the 32-bit here to the 32-bit above, you see that it
changes from 32-bit memory addressing to 16-bit memory addressing for
32-bit code. I.e., switches address modes.

If you compare the 64-bit here to the 64-bit above, you see that it
changes from 64-bit memory addressing to 32-bit memory addressing for
64-bit code. I.e., switches address modes.

> In intel manual i
> see:
> 80 /2 ib ADC r/m8, imm8


The 80 corresponds to the 80.
The 10 corresponds to the /2.
The 07 corresponds to the ib.

The 67h is address size override for mixed-mode instructions. I.e., it
changes the address size of the instruction for the current mode.

There is also a 66h. The 66h is operand size override for mixed-mode
instructions. I.e., it changes the operand size of the instruction for
the current mode.

I recently answered this same question on alt.os.development for you.


You need to memorize that 67h and 66h are address and operand size
overrides, respectively, for mixed-mode x86 instructions.

Rod Pemberton
P.S. Rick stop harassing Peter. You're the first to reply to his posts.
Rick C. Hodgin (01-06-19, 05:33 AM)
On Saturday, January 5, 2019 at 8:31:51 PM UTC-5, Rod Pemberton wrote:
> P.S. Rick stop harassing Peter...


How was my reply was harassment, Rod? I answered his question,
and pointed him to Intel's own documentation.

Perhaps you should run a self-diagnostic. :-)
Peter Cheung (01-06-19, 07:37 PM)
Thanks all, but i still don't know when to add 67, for example:

adc ah, 0x7, only in 32 bits mode has 67, 16 bits and 64 bits NO 67

But adc byte [eax], 16 and 64 bits has 67

why?
Rick C. Hodgin (01-06-19, 07:50 PM)
On 1/6/2019 12:37 PM, Peter Cheung wrote:
> Thanks all, but i still don't know when to add 67, for example:
> adc ah, 0x7, only in 32 bits mode has 67, 16 bits and 64 bits NO 67
> But adc byte [eax], 16 and 64 bits has 67
> why?


When you use 16-bit registers (bx, si, di, bp), you are able to
use that instruction as it is in the Intel documentation for its
encoding.

When you want to use the 386 extensions (eax, ebx, ecx, edx, esi,
edi, ebp, or esp) to address memory, you need to use the 0x67 pre-
fix override to tell the instruction decoder that you're not using
16-bit registers, but you'll be using an extended 32-bit addressing
mode, and it will have information in the SIB byte which follows
the normal opcode, and precedes the immediate value.

SIB stands for "Scale/Index Byte" and it has those properties in
its encoding. It is enabled by the 0x067 prefix. When you encode
your assembly in 16-bit mode, it looks at what you're doing:

16-bit instrucitons:

ADC byte ptr [bx],7 ; No 0x67 prefix
ADC byte ptr [si],7 ; No 0x67 prefix
ADC byte ptr [di],7 ; No 0x67 prefix
ADC byte ptr [bp],7 ; No 0x67 prefix

32-bit instructions require more information, hence the prefix,
and hence the SIB:

ADC byte ptr [eax],7 ; 0x67 prefix
ADC byte ptr [ebx],7 ; 0x67 prefix
ADC byte ptr [ecx],7 ; 0x67 prefix
ADC byte ptr [edx],7 ; 0x67 prefix
ADC byte ptr [esi],7 ; 0x67 prefix
ADC byte ptr [edi],7 ; 0x67 prefix
ADC byte ptr [ebp],7 ; 0x67 prefix
ADC byte ptr [esp],7 ; 0x67 prefix

Those extra 32-bit registers require the 0x67 prefix so the decoder
knows you're using 32-bit registers, not 16-bit registers.

You also have new abilities for your addressing when you use 0x67
prefix, which is stored in the SIB. The SIB shows how the encoded
bits are expanded, as [eax], [ebx], etc., are just one mode. The
SIB can contain information like [eax+ebx], or [edx+edi], etc. It
can also contain scaling, such as [eax*2] or [ebx+esi*4], etc. It
also stores the offset form, such as [eax+16] or [ebx+edi*8+12],
etc.

It is a very flexible extension, and the 0x67 opcode prefix enables
it. And, when you're in 32-bit mode, you can use the 0x67 to go
the other way (to tell it to use 16-bit forms, rather than 32-bit
forms).
Rod Pemberton (01-07-19, 09:08 AM)
On Sun, 6 Jan 2019 09:37:58 -0800 (PST)
Peter Cheung <mcheung63> wrote:

> Thanks all, but i still don't know when to add 67,


The assembler or compiler usually adds it for you. Most of them
recognize that the address size or operand size is different from the
code segment size and insert 67h/66h as needed. Old or obsolete
assemblers might not support this.

> for example:
> adc ah, 0x7, only in 32 bits mode has 67, 16 bits and 64 bits NO 67


No.

"adc ah, 0x7" is the same for 16-bits, 32-bits, probably 64-bits,
unless your assembler is old or broken or incomplete.

"adc byte [ax], 0x7" needs an override, but it's an operand override
66h, not and address override 67h.

> [override usage]


16-bit code doesn't support using 32-bit registers. Only 16-bit and
8-bit registers are supported in 16-bit code, without the use of
overrides (available for 386 or later).

To use a 32-bit register or 32-bit memory address mode in 16-bit code
segment, you must use an override.

Similarly,

32-bit code doesn't support using 16-bit registers. Only 32-bit and
8-bit registers are supported in 32-bit code, without the use of
overrides (available for 386 or later).

To use a 16-bit register or 16-bit memory address mode in 32-bit code
segment, you must use an override.

Sorry, I'm not fully up to date on 64-bits, but I think its 64-bit or
32-bit with overrides.

> But adc byte [eax], 16 and 64 bits has 67


Again, I think this is 66h not 67h. You'd need 66h for 16-bits.
However, "adc byte [ax], 0x07" needs a 66h in 64-bits.

> why?


The x86 processor is not orthogonal. It's ad hoc. They changed things
as they went along. Broke things. Improved things. Redesigned
things. The processor wasn't designed at once. It was incremental.

The x86 was a CISC design before the terms CISC and RISC were even
created. The x86 has different addressing modes, different
instructions, and many instruction encodings unique for each
processor mode. I.e., the binary decodes as a different instruction
for a different mode.

I'm not sure if you're having difficulty understanding the placement of
overrides, or if you're confusing addressing modes and/or both. It
seems like you don't fully understand the basic addressing modes for
each mode, which are different for each. This seems to be adding to the
confusion about how the overrides 66/67 work. You seem to be expecting
the overrides to be orthogonal, or have symmetry from mode to mode, or
for their usage and application to make sense. In other words, they
don't any make sense across all modes, but only make sense when applied
from one mode to get to another.

For 16-bit mode,
(from a document I created, posted to Usenet a few times)

16-bit register addressing modes:
al,cl,dl,bl,ah,ch,dh,bh (8-bit registers)
ax,cx,dx,bx,sp,bp,si,di (16-bit registers)

16-bit memory addressing modes:
ds:[bx+si+(no offset,8-bit offset,16-bit offset)]
ds:[bx+di+(no offset,8-bit offset,16-bit offset)]
ss:[bp+si+(no offset,8-bit offset,16-bit offset)]
ss:[bp+di+(no offset,8-bit offset,16-bit offset)]
ds:[si+(no offset,8-bit offset,16-bit offset)]
ds:[di+(no offset,8-bit offset,16-bit offset)]
ss:[bp+(8-bit offset,16-bit offset)] (NOTE: no 'no offset' form)
ds:[16-bit displacement]
(NOTE:above replaces 'no offset' form of bp+offset)
ds:[bx+(no offset,8-bit offset,16-bit offset)]

So, you can see that al, ah, ax, are supported in 16-bit mode for
registers, but eax, rax aren't. To use eax, you must use a 66/67
override. You can't use rax at all.

Also, you can see that there is no "adc [eax], ..." instruction, nor
is there a "adc [ax], ..." instruction, as the memory addressing modes
don't support using eax or ax, but use combinations of bx, di, si, bp,
i.e., "adc [bx+si], ...". To use "adc [eax], ..." in 16-bit code, you
must use a 66/67 override to select a 32-bit instruction encoding which
supports addressing using eax.

For 32-bit mode, (again my representation)

32-bit register addressing modes:
al,cl,dl,bl,ah,ch,dh,bh (8-bit registers)
eax,ecx,edx,ebx,esp,ebp,esi,edi (32-bit registers)

32-bit memory addressing modes:
ds:[eax+(no offset,8-bit offset,32-bit offset)]
ds:[ecx+(no offset,8-bit offset,32-bit offset)]
ds:[edx+(no offset,8-bit offset,32-bit offset)]
ds:[ebx+(no offset,8-bit offset,32-bit offset)]
SIB forms (**) (no esp+offset mode - SIB encoding allows esp+offset)
ss:[ebp+(8-bit offset,32-bit offset)] (NOTE: no 'no offset' form)
ds:[32-bit displacement]
(NOTE:above replaces 'no offset' form of ebp+offset)
ds:[esi+(no offset,8-bit offset,32-bit offset)]
ds:[edi+(no offset,8-bit offset,32-bit offset)]

(**) two SIB forms (scaled index byte):

ds/ss:[(reg0a,32-bit displacement)+(reg1*n,none)]
ds/ss:[reg0b+(reg1*n,none)+(8-bit offset,32-bit offset)]

segment is ds, except if reg0a or reg0b is esp or ebp, then it's ss
reg0a=eax,ecx,edx,ebx,esp,esi,edi,32-bit displacement(ebp) (no ebp)
reg0b=eax,ecx,edx,ebx,esp,esi,edi,ebp
reg1=eax,ecx,edx,ebx,ebp,esi,edi,none(esp) (no esp)
n=1,2,4,8

So, you can see that al, ah, eax are supported in 32-bit mode for
registers, but ax, rax aren't. To use ax, you must use a 66/67
override. You can't use rax at all.

Take note of how different the memory addressing modes are for 16-bit
and 32-bit code. 32-bit mode uses eax, ecx, edx, ebx ..., but 16-bit
mode uses bx+si, bx+di, bp+si, bp+di, ... Also note that 32-bit memory
addressing has a special SIB form, an extended instruction encoding
created for 32-bit mode, which has an extra byte. These decode to a
different 16-bit instruction with an extra byte inserted into the
instruction stream, i.e., bad decode for wrong mode. Also note that
16-bit registers aren't available without overrides for 32-bit mode, and
vice-versa.

In other words, the instruction encodings for 16-bit code which address
memory are different from the encodings for 32-bit code. This is
called non-orthogonal. E.g., a 16-bit instruction addressing memory via
bx+si will decode to eax for 32-bit code, and probably rax for 64-bit
code (or maybe still eax).

Sorry, you'll have to read up on 64-bit addressing modes on your own.

See this post further down at "<--start-->" for my 16-bit/32-bit
x86 instruction notes where the address/register info above came from.
This long post includes a concise summary of many other useful bits of
information on x86 instructions, i.e., all of the non-orthogonal
"features", not summarized in the manuals, e.g., hardcoded registers,
hardcoded constants, special functionality, mode limitations, etc.



Rod Pemberton
wolfgang kern (01-07-19, 01:59 PM)
On 1/7/2019 8:08 AM, Rod Pemberton wrote:

....

>> for example:


>> adc ah, 0x7, only in 32 bits mode has 67, 16 bits and 64 bits NO 67


> No.


> "adc ah, 0x7" is the same for 16-bits, 32-bits, probably 64-bits,
> unless your assembler is old or broken or incomplete.


yes,
80 D4 07 ADC AH,7
is equal for all modes and any 66/67 prefix were ignored here.

> "adc byte [ax], 0x7" needs an override, but it's an operand override
> 66h, not and address override 67h.


ADC byte [ax],7 ??? doesn't exist in my docs
and all 'byte'-instructions ignore 66.

16-bit:
80 10 07 ADC byte [bx+si],7
67 80 10 07 ADC byte [eax] ,7

32-bit:
67 80 10 07 ADC byte [bx+si],7
80 10 07 ADC byte [eax] ,7

64-bit:
80 10 07 ADC byte [rax] ,7 ;full 64 bit address used
67 80 10 07 ADC byte [eax] ,7 ;upper bits ignored (aka ZERO-page)
__
wolfgang
Rod Pemberton (01-08-19, 02:17 AM)
On Mon, 7 Jan 2019 12:59:56 +0100
wolfgang kern <nowhere> wrote:

> > "adc byte [ax], 0x7" needs an override, but it's an operand override
> > 66h, not and address override 67h.

> ADC byte [ax],7 ??? doesn't exist in my docs
> and all 'byte'-instructions ignore 66.


Sorry, I was attempting to match the MASM-like syntax he was using,
while using NASM, and I clearly assembled/disassembled something
wrongly there, i.e., 66h.

Rod Pemberton
Peter Cheung (01-12-19, 08:08 PM)
ok, thank you all, please verify these statements:

1. in 16 bits, if you use 32 bit register, you need to add 67
2. in 32 bits, if you use 16 bit register, you need to add 67
3. in 64 bits, if you use 16 bit register, no need to add 67. But need to add 67 if you use 32 bit register

The above statements CAN cover all scenarios, right?
Rick C. Hodgin (01-14-19, 03:48 PM)
On Saturday, January 12, 2019 at 1:08:38 PM UTC-5, Peter Cheung wrote:
> ok, thank you all, please verify these statements:
> 1. in 16 bits, if you use 32 bit register, you need to add 67
> 2. in 32 bits, if you use 16 bit register, you need to add 67
> 3. in 64 bits, if you use 16 bit register, no need to add 67. But need to add 67 if you use 32 bit register
> The above statements CAN cover all scenarios, right?


There's a map given by Intel in their IA-32/Intel64 manual:

Page 81:


Tables 3.3, and 3.4. The Y and N indicate if the prefix is needed.
Peter Cheung (01-16-19, 07:58 PM)
thank you
Rick C. Hodgin (Today, 12:46 AM)
On Wednesday, January 16, 2019 at 12:58:24 PM UTC-5, Peter Cheung wrote:
> thank you


You say "thank you" here, and then threaten to send radical
Muslims to attack me and my family on alt.os.development a
few days later?

From this day forward, Peter, you are on your own. I will
no longer write a single post to you in replies asking for
help or any other purpose.

May you find what you're looking for. Good bye.
Similar Threads