2016-11-22 81 views
2

所以我试图转换从C以下分配到内联汇编移动变量CL和使用内联汇编

resp = (0x1F)&(letter >> (3 - numB)); 

假设执行SHR该变量的声明有以下几种

unsigned char resp; 
unsigned char letter; 
int numB; 

所以我试过以下内容:

_asm { 
     mov ebx, 01fh 
     movzx edx, letter 
     mov cl,3 
     sub cl, numB // Line 5 
     shr edx, cl 
     and ebx, edx 
     mov resp, ebx 
} 

或以下

_asm { 
      mov ebx, 01fh 
      movzx edx, letter 
      mov ecx,3 
      sub ecx, numB 
      mov cl, ecx // Line 5 
      shr edx, cl 
      and ebx, edx 
      mov resp, ebx 
    } 

在这两种情况下,我得到的大小操作数错误在5号线 我怎样才能达到正确的转变?

+1

你看过编译器会为此生成什么吗? – EOF

+3

CL是ECX的低字节。如果您删除无意义的'mov cl,ecx',您的第二个版本看起来不错。由于'numB'是32位,所以你必须在32位寄存器中使用它。 (或者,也许'sub cl,byte ptr numB'只加载低字节,因为SHR无论如何都掩盖了移位计数。) –

回答

1

E*X寄存器是32位,而*L寄存器是8位。类似地,在Windows上,int类型是32位宽,而char类型是8位宽。您不能在一条指令内任意混合这些尺寸。

所以,在第一个代码段:

sub cl, numB // Line 5 

这是错误的,因为cl寄存器存储一个8位的值,而numB变量是int类型的,其中存储一个32位的值。您不能从8位值中减去32位值;指令SUB的两个操作数必须具有相同的大小。

类似地,在第二个代码段:

mov cl, ecx // Line 5 
你正在试图在ECX移动32位值转换成8位寄存器CL

。没有某种截断就不可能发生,所以你必须明确地指出它。 MOV指令要求它的两个操作数具有相同的大小。

MOVZXMOVSX是显而易见的此规则的例外是,操作数类型必须为单个指令相匹配。这些指令零扩展或符号扩展,分别,较小的值,使得它可以被存储到larger-大小的寄存器)。

但是,在这种情况下,你甚至不需要的MOV指令。请记住,CL只是完整的32位ECX寄存器的低8位。因此,设置ECX也会隐式设置CL。如果你只需要低8位,你可以在随后的指令中使用CL。因此,你的代码就变成了:

mov ebx, 01fh    ; move constant into 32-bit EBX 
    movzx edx, BYTE PTR letter ; zero-extended move of 8-bit variable into 32-bit EDX 
    mov ecx, 3     ; move constant into ECX 
    sub ecx, DWORD PTR numB ; subtract 32-bit variable from ECX 
    shr edx, cl    ; shift EDX right by the lower 8 bits of ECX 
    and ebx, edx    ; bitwise AND of EDX and EBX, leaving result in EBX 
    mov BYTE PTR resp, bl  ; move lower 8 bits of EBX into 8-bit variable 

对于与上述相同的操作数大小匹配的问题,我也不得不改变最终MOV指令。您不能将存储在32位寄存器中的值直接移动到8位变量中。您必须移动较低的8位或较高的8位,从而可以使用BLBH寄存器,它们是8位,因此与resp的大小相匹配。在上面的代码中,我假定你只需要低8位,所以我使用了BL

另请注意,我已使用BYTE PTRDWORD PTR规范。这些在MASM(或Visual Studio的内联汇编程序)中不是绝对必需的,因为它可以从变量类型中推导出类型的大小。但是,我认为它增加了可读性,并且通常是推荐的做法。 DWORD表示32位;它与int和32位寄存器(E*X)的大小相同。 WORD表示16位;它与short和一个16位寄存器(*X)的大小相同。​​表示8位;它与char和一个8位寄存器(*L*H)的大小相同。