2016-11-22 5 views
2

Так я пытаюсь перевести следующее задание из C встраивать сборкипеременных Переместить в КНЕ и выполнить SHR с помощью ассемблерных

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

Предполагая, что объявление переменных являются следующими

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-битное значение , Вы не можете вычесть 32-битное значение из 8-битного значения; оба операнда в команде SUB должны быть одного размера.

Кроме того, в вашем втором фрагменте кода:

mov cl, ecx // Line 5 

вы пытаетесь переместить 32-битное значение в ECX в 8-битном CL регистра. Это не может произойти без какого-либо усечения, поэтому вы должны указать его явно. Инструкция MOV требует, чтобы оба его операнда имели одинаковый размер.

(MOVZX и MOVSX являются очевидными исключениями из этого правила, что типы операндов должны совпадать для одной инструкции. Эти инструкции имеют нулевое расширение или знак-расширение, соответственно, меньшее значение, так что оно может быть сохранено в более крупном,)

Однако в этом случае вы даже не нуждаетесь инструкцию MOV. Помните, что CL - это всего лишь 8 бит полного 32-разрядного регистра ECX. Поэтому установка 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 бит, позволяя использовать либо регистры BL, либо BH, которые являются 8 битами и поэтому соответствуют размеру resp. В приведенном выше коде я предположил, что вам нужны только младшие 8 бит, поэтому я использовал BL.

Также обратите внимание, что я использовал спецификации BYTE PTR и DWORD PTR. Это не обязательно необходимо в MASM (или встроенном ассемблере Visual Studio), поскольку он может выводить размеры типов из типов переменных. Тем не менее, я думаю, что это повышает удобочитаемость и, как правило, рекомендуется. DWORD означает 32 бит; он имеет тот же размер, что и int, и 32-разрядный регистр (E*X). WORD означает 16 бит; он имеет тот же размер, что и short, и 16-разрядный регистр (*X). BYTE означает 8 бит; он имеет тот же размер, что и char, и 8-битный регистр (*L или *H).

 Смежные вопросы

  • Нет связанных вопросов^_^