2016-11-22 67 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)的大小相同。