Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.21.104.109] |
|
Сообщ.
#1
,
|
|
|
Портировал на ассемблер один проект из Delphi (1500 строк), компилирую его из Visual Studio с помощью masm. В среде выбрал соотв. опции (Build Dependencies -> masm) и в опциях проекта Microsoft Macro Assembler. Под 32 работает. Теперь хочу портировать код под 64, да так чтобы не писать новый код со всеми особенностями 64 разработки, а прям в этом же файле с условными компиляциями и макроопределениями, к примеру
IFDEF RAX _WIN64 equ TRUE ELSE _WIN32 equ TRUE ENDIF IFDEF _WIN32 .386 .model flat, stdcall option casemap :none ; case sensitive include c:\masm32\include\windows.inc include c:\masm32\include\kernel32.inc my_eax equ eax ELSE include c:\masm64\include64\win64.inc include c:\masm64\include64\kernel32.inc my_eax equ rax ENDIF 1. Если переопределить все регистры. 2. В участках кода где вызываются функции с помощью условных компиляций выделить место в стеке sub rsp, 32 3. Заменить структуры и типы на 64 вариант, где это требуется. 4. Выровнять границу в нужных местах. и т.д. Насколько адекватна затея всё это городить в одном файле исходного текста? Дело в том что по определённым причинам нужно именно в одном файле. Какие могут быть ещё нюансы, чтобы грамотно всё сделать? Ещё такой вопрос, взял отсюда комплект под 64 и сгенерил либы инклуды Library update May 2018 может это всё не нужно раз из студии компилирую, как через неё можно сгенерировать инклуды и т.д. Спасибо! |
Сообщ.
#2
,
|
|
|
kin01, тут зависит от того, что в исходнике и как он написан.
Теоретически, это возможно (правда, некоторые возможности будут утеряны, например, можно было бы оптимизировать код с учётом наличия r8-r15 и SSE2), а практически все может оказаться сложнее, чем кажется (тем более, если прога длинная). Нюансы: • Могут поехать размеры данных из-за изменения размеров операндов. К примеру, есть dd и dword ptr. Нужно ли их приводить к dq и qword ptr? Далеко не всегда, зависит от конкретном ситуации. К примеру, в виндовых структурах есть dw-поле, а есть lpsz. Поле dw Всегда будет 32-битным, а lpsz – зависит от разрядности. При этом, если мы записываем что-то с помощью mov dwSomeData,eax, то mov dwSomeData,rax вызовет ошибку. Но тут можно играться с названиями универсальных регистров. Там, где нужно всегда использовать eax, указывать явно: eax. А где операнд зависит от разрядности – my_eax. Аналогично с dd, dword ptr. • То же самое, но с непосредственными значениями. Что значит 0FFFF0000h? Что у нас только 16 младших разрядов должны быть обнулены или что старшие 32 (в 64 битах) тоже? • Как сделаны вызовы и объявления функций? Если это просто метки и push+call, то будет геморно (потому как фреймы устроены по-разному, да и параметры передаются по-разному). Тут sub rsp,32 может оказаться недостаточно, т.к. нужно выравнивать стек до 8 байт. Но если через invoke/proc, тогда всё должно работать само собой. Но! Вызов invoke SomeFunc, eax, ecx сработает в Win32, а вот в Win64 (invoke SomeFunc, rax, rcx) – не факт, т.к. invoke скорее всего заносит в регистры-параметры данные тупо последовательно (у меня именно такой вариант, по приведённой вами ссылке – не знаю, может, там исправлено), т.е. это развернётся в: mov rcx,rax mov rdx,rcx ; опа... а rcx у нас уже перезаписан! call [Function] • Если вдруг в коде используются инструкции, которые в 64-х битах недоступны (скажем, das, например, для перевода в 16-ричное число), то этот кусок кода придётся переписывать. • Ну и пр., о чём я ещё не вспомнил. Пробуйте. Всё реально Добавлено Цитата kin01 @ Думаю, что нужно, т.к. когда я делал подобное, я не нашёл у себя файла, к примеру, kernel32.inc и пр., и брал из masm32 и стороннего комплекта под ml64. Ещё такой вопрос, взял отсюда комплект под 64 и сгенерил либы инклуды Library update May 2018 может это всё не нужно раз из студии компилирую, как через неё можно сгенерировать инклуды и т.д. Добавлено По трудоёмкости сложно сказать, всё сильно зависит от кода. Может, он там так написан, что проще сделать if _WIN32 ; весь код под 32 elseif _WIN64 ; весь код под 64 endif Добавлено Посмотрел вашу ссылку. А что там, собственно, ценного? Это чисто библиотека m64lib, там нет inc'ов вообще. Вам надо вот это: http://xk8.ru/ml64 |
Сообщ.
#3
,
|
|
|
не то скопировал. ниже по ссылке есть makeall.bat который всё делает.
Current build of the 64 bit MASM SDK Добавлено но по сути нужны только *.inc т.к. в студии всё есть. |
Сообщ.
#4
,
|
|
|
Оказалось достаточно легко написать исходный код для двух платформ. Помимо переопределения регистров:
rax equ eax rcx equ ecx rdx equ edx rbx equ ebx rbp equ ebp rsp equ esp rsi equ esi rdi equ edi r9 equ ebx r8d equ ebx r8b equ bl r8 equ ebx переопределил типы, структуры Pointer typedef PVOID; NativeInt typedef SIZE_T; UIntPtr typedef SIZE_T HINST typedef SIZE_T; Integer typedef DWORD; TMemoryModule typedef Pointer; Cardinal typedef Integer; PUINT16 typedef PTR UINT16; PUINT_PTR typedef PTR UINT_PTR PPointer typedef PTR Pointer PWord typedef PTR Word PAnsiChar typedef Pointer PByte typedef Pointer и использовал несколько макросов ;-------------------------------------------- ; CROSS ;-------------------------------------------- pmx macro arg1, arg2 ifdef win32 push arg2 else mov arg1, arg2 endif endm plx macro arg1, arg2 ifdef win32 lea arg1, arg2 push arg1 else lea arg1, arg2 endif endm CROSS_MOVSXD macro arg1, arg2 IFDEF win64 movsxd arg1, arg2 ELSE mov arg1, arg2 ENDIF ENDM получилось нечто такого pmx rdx, rdx mov rax, codebase mov rcx, section mov ecx, (IMAGE_SECTION_HEADER ptr [rcx]).VirtualAddress add rcx, rax pmx rcx, rcx call VirtualAlloc почти нет условных компиляций в коде. только в препроцессоре. |