Discussion:
movzx from 32 to 64 bis in AMD64/EM64T
(too old to reply)
Pierre Lopan
2005-02-01 00:33:52 UTC
Permalink
hello,

the 64 bits ML.EXE compiler for AMD64/Intel EM64T accept

movzx rbx,ax

movsxd rbx,eax



but don't acces

movzx rbx,eax

saying "error A2070 : invalid instruction operand"

I want extend an unsigned 32 bits integer to a 64 bits interger.





http://www.intel.com/technology/64bitextensions/30083502.pdf page 84 talk
about

"MOVZX r64,r/m32"



Amd manual contain same reference.



any idea?
wolfgang kern
2005-02-01 02:22:01 UTC
Permalink
"Pierre Lopan" wrote:

| the 64 bits ML.EXE compiler for AMD64/Intel EM64T accept
| movzx rbx,ax
| movsxd rbx,eax
| but don't acces movzx rbx,eax

| saying "error A2070 : invalid instruction operand"
|
| I want extend an unsigned 32 bits integer to a 64 bits interger.

| http://www.intel.com/technology/64bitextensions/30083502.pdf page 84 talk
| about

| "MOVZX r64,r/m32"

I don't have a 64' to play with, but I currently work on a
64-bit disassembler (32-bit program).

Intel EM64 30083502.pdf (on page 82) says:

0f b7 ... MOVZX r32,r/m16 (same as AMD)
48 0f b7 ... MOVZX r64,r/m32 (but isn't shown in the AMD manual)

My AMD-64 24594.pdf volume3 doesn't show this option,
but it got MOVSXD which can be modified to become MOVZXD by
deleting the REXW override.

So my disassembler will produce this syntax:

48 0f b7(64,32) MOVZXD ... (MOVXZ 64,32 in Intel docs only)
63 r64/rm32 MOVZXD ... (syntax not mentioned in the AMD manuals)
48 63 r64/rm32 MOVSXD ... (here AMD explains the behaviour w/o 48h)

Intel says on the latter:
The use of MOVSXD without REX.W in 64-bit mode is discouraged,
Regular MOV should be used instead of using MOVSXD without REX.W.

Perhaps a buggy Intel statement by not knowing the undefined ?
(when looking to Intel-manuals this sounds very familiar to me)

Can't tell if there is really a difference in the two CPUs
or if just the manuals interpret it apart.
.. and your compiler seems to be confused also :)

I don't know about your tool, but I'd try "MOVZXD rbx,eax"
or try a 48h prefix on a MOVZX ebx,ax.
Just a thought from the distance...

__
wolfgang
Matt
2005-02-01 05:30:13 UTC
Permalink
"wolfgang kern" <***@nevernet.at> wrote in message news:ctmofb$2oq$***@newsreader1.utanet.at...
[...]
Post by wolfgang kern
0f b7 ... MOVZX r32,r/m16 (same as AMD)
48 0f b7 ... MOVZX r64,r/m32 (but isn't shown in the AMD manual)
It isn't shown because it's wrong. Adding the REX.W prefix makes that "movzx
r64, r/m16". The closest you can get to an official movzxd is 8B /rm with
the ModR/M byte being >= 0xC0 (that is, 2 registers). AMD did not create a
movzxd because it isn't needed. When 32-bit registers are the target of
computation, the upper 32-bits is automatically zeroed.

Refer to page 83 of volume 1, section 3.4.5.

I have not tested any of this, but it doesn't make any sense at all to
change the size of the second operand, and AMD's manual says nothing about
it. I am more inclined to believe that Intel's manual is just plain buggy
here.
Post by wolfgang kern
My AMD-64 24594.pdf volume3 doesn't show this option,
but it got MOVSXD which can be modified to become MOVZXD by
deleting the REXW override.
Not exactly. Without the REX.W prefix, movsxd becomes a mov with the same
implicit zero-extension behavior. Without the REX.W prefix, it essentially
becomes "movzxd". Check page 203 of volume 3, the entry for "movsxd". It
explicitly states what I have said here.
Post by wolfgang kern
48 0f b7(64,32) MOVZXD ... (MOVXZ 64,32 in Intel docs only)
63 r64/rm32 MOVZXD ... (syntax not mentioned in the AMD manuals)
48 63 r64/rm32 MOVSXD ... (here AMD explains the behaviour w/o 48h)
The use of MOVSXD without REX.W in 64-bit mode is discouraged,
Regular MOV should be used instead of using MOVSXD without REX.W.
Perhaps a buggy Intel statement by not knowing the undefined ?
(when looking to Intel-manuals this sounds very familiar to me)
They are right, but it is silly to call this opcode movzxd. Again, all
instructions will implicitly zero-extend 32-bit results to 64-bits, so it's
really pointless to have a movzxd instruction. That's why AMD didn't. There
really isn't any difference between this hypothetical "movzxd" instruction
and a regular "mov" instruction.
Post by wolfgang kern
Can't tell if there is really a difference in the two CPUs
or if just the manuals interpret it apart.
.. and your compiler seems to be confused also :)
I don't know about your tool, but I'd try "MOVZXD rbx,eax"
or try a 48h prefix on a MOVZX ebx,ax.
Just a thought from the distance...
The latter would not be the same as the former. Adding REX.W would cause it
to zero-extend ax -> rbx, not eax -> rbx.

-Matt
wolfgang kern
2005-02-02 10:47:09 UTC
Permalink
Hi Matt,

[...]
| > Intel EM64 30083502.pdf (on page 82) says:
| >
| > 0f b7 ... MOVZX r32,r/m16 (same as AMD)
| > 48 0f b7 ... MOVZX r64,r/m32 (but isn't shown in the AMD manual)
|
| It isn't shown because it's wrong. Adding the REX.W prefix makes that "movzx
| r64, r/m16". The closest you can get to an official movzxd is 8B /rm with
| the ModR/M byte being >= 0xC0 (that is, 2 registers). AMD did not create a
| movzxd because it isn't needed. When 32-bit registers are the target of
| computation, the upper 32-bits is automatically zeroed.
|
| Refer to page 83 of volume 1, section 3.4.5.
|
| I have not tested any of this, but it doesn't make any sense at all to
| change the size of the second operand, and AMD's manual says nothing about
| it. I am more inclined to believe that Intel's manual is just plain buggy
| here.
|
| > My AMD-64 24594.pdf volume3 doesn't show this option,
| > but it got MOVSXD which can be modified to become MOVZXD by
| > deleting the REXW override.
|
| Not exactly. Without the REX.W prefix, movsxd becomes a mov with the same
| implicit zero-extension behavior. Without the REX.W prefix, it essentially
| becomes "movzxd". Check page 203 of volume 3, the entry for "movsxd". It
| explicitly states what I have said here.

| > So my disassembler will produce this syntax:
| > 48 0f b7(64,32) MOVZXD ... (MOVXZ 64,32 in Intel docs only)

I'll immediately correct this one and add one more entry to the
Intel-doc bugs list.

| > 63 r64/rm32 MOVZXD ... (syntax not mentioned in the AMD manuals)
| > 48 63 r64/rm32 MOVSXD ... (here AMD explains the behaviour w/o 48h)
| >
| > Intel says on the latter:
| > The use of MOVSXD without REX.W in 64-bit mode is discouraged,
| > Regular MOV should be used instead of using MOVSXD without REX.W.
| >
| > Perhaps a buggy Intel statement by not knowing the undefined ?
| > (when looking to Intel-manuals this sounds very familiar to me)

| They are right, but it is silly to call this opcode movzxd. Again, all
| instructions will implicitly zero-extend 32-bit results to 64-bits, so it's
| really pointless to have a movzxd instruction. That's why AMD didn't. There
| really isn't any difference between this hypothetical "movzxd" instruction
| and a regular "mov" instruction.

Oh Yes I forgot, this is one of the points why I don't like these 64's,
but to show this hidden behaviour I'll add some 'MOVZXD'-equivalent
mnemonics also for the 64' mov group for my current disassemblers
output options:

8b c1 RAX = Zq ECX Terse-styled
RQ0 = Zq RD1 KESYS hexwork
MOVZXD rax,ecx Intel/AMD explaining
MOV eax,ecx Intel/AMD (as is)


| > Can't tell if there is really a difference in the two CPUs
| > or if just the manuals interpret it apart.
| > .. and your compiler seems to be confused also :)
| >
| > I don't know about your tool, but I'd try "MOVZXD rbx,eax"
| > or try a 48h prefix on a MOVZX ebx,ax.
| > Just a thought from the distance...
|
| The latter would not be the same as the former. Adding REX.W would cause it
| to zero-extend ax -> rbx, not eax -> rbx.

Thanks for correction, now I know where confusion come from:
one more time from the good Intel books.

__
wolfgang

Matt
2005-02-01 05:13:21 UTC
Permalink
Post by Pierre Lopan
hello,
the 64 bits ML.EXE compiler for AMD64/Intel EM64T accept
movzx rbx,ax
movsxd rbx,eax
but don't acces
movzx rbx,eax
saying "error A2070 : invalid instruction operand"
I want extend an unsigned 32 bits integer to a 64 bits interger.
[...]

Try:
mov ebx, eax

The AMD manuals very clearly state that writing to a 32-bit register will
zero out the upper half of a 32-bit register. There is no "movzxd"
instruction because it isn't necessary. In most cases you can probably even
optimize away the mov instruction simply by making a 32-bit register (eax,
ecx, ..., r8d, r9d, ...) the target of a computation.

-Matt
Gilles Vollant
2005-02-02 00:47:35 UTC
Permalink
Ok, you are right ! I made a test :

In 64 bits world :
mov ax,bx : copy the 16 lower bits of rbx to rax and did not modify the
other higher 48 bits of rax
mov eax,ebx : copy the 32 lower bits of rbx to rax and clear to 0 the other
higher 32 bits of rax


in the 32 bits world :
mov ax,bx : copy the 16 lower bits of rbx to rax and did not modify the
other higher 16 bits of rax


The logic used to expand x86 for 16 to 32 bits 20 year ago (80386 - 1985) is
not the same used on Amd64 !
Loading...