Сборка, преобразующая MOV / MOVZX и MOVSX в код C (без встроенного asm)

#c #assembly #x86 #transformation #code-translation

#c #сборка #x86 #преобразование #код-перевод

Вопрос:

Для эмулятора asm я пытаюсь написать, чтобы преобразовать код ASM в эквивалентный рабочий код, который просто работает.. лучшим кодом будет тот, который можно выполнить в одну строку или в две-три, не заботясь о скорости.

Насколько я понимаю. MOVZX будет таким же, как MOV .. если сделано на C .

MOV преобразование.

 MOV ESI,DWORD PTR [ESP 8]
  

было бы похоже

 regs.d.esi = *(unsigned int *)(regs.d.esp 0x00000008);
  

MOVZX преобразование.

 MOVZX EAX,BYTE PTR DS:[EDI]
  

было бы похоже

 regs.d.eax = *(unsigned char *)(regs.d.edi);
  

практически то же самое, что и когда-либо.

Теперь MOVSX у меня возникли проблемы с преобразованием в простой код C .. похоже, он такой же, как два выше.. за исключением того, что он пытается добавить как можно больше полностью установленных битов перед перемещенным значением.. Нравится

000000C7 становится FFFFFFC7

Ответ №1:

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

 regs.d.eax = *(signed char *)(regs.d.edi); // movsx eax, byte ptr ds:[edi]
  

Комментарии:

1. Как насчет.. MOVSX EAX,AL это правильно? regs.d.eax = (signed char)(regs.h.al);

2. @SSpoke Вам нужно быть осторожным при приведении между разными целочисленными типами, но я почти уверен, что приведение между подписанными и неподписанными типами одинакового размера безопасно. (Вам не нужно беспокоиться о неявном приведении к типу regs.d.eax , поскольку это фактический movsx )

3. al = unsigned char хотя. все еще небезопасно? все это уже применено.

4. @SSpoke Нет, приведение между типами одинакового размера безопасно (по крайней мере, это сработало правильно в моих быстрых тестах. Может быть, кто-нибудь может процитировать стандарт?). Вы могли бы столкнуться с проблемами, если al бы был какой-то другой размер.

5. спасибо, что я хотел знать, что это никогда не будет другого размера. union _regs { struct { unsigned int eax, ebx, ecx, edx, esi, edi, ebp, esp; } d; struct { unsigned short ax, hax, bx, hbx, cx, hcx, dx, hdx, si, hsi, di, hdi, bp, hbp, sp, hsp; } x; struct { unsigned char al, ah, hax[2], bl, bh, hbx[2], cl, ch, hcx[2], dl, dh, hdx[2], rest[16]; } h; } regs;

Ответ №2:

Самый быстрый способ найти очень быстрые эквиваленты MOVSX и MOVXZ на языке C — это просто присвоение целочисленной переменной типа с младшими битами типу с более высокими битами. Обе переменные должны быть преобразованы либо в подписанный тип (для MOVSX), либо в неподписанный тип (MOVZX).

Например, эквивалент C «movzx ebx, al» будет:

 (unsigned int) ebx = (unsigned char) al;
  

Эквивалент C «movsx ebx, al» будет:

 (signed int) ebx = (signed char) al;
  

Просто убедитесь, что ваш тип char равен 8 битам, а ваш тип int — 32 битам, и так далее.