#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 битам, и так далее.