2012-05-22 2 views
6

У меня есть пример исходного кода для OpenGL, я хотел скомпилировать 64-битную версию (используя Delphi XE2), но есть некоторый код ASM, который не удается скомпилировать, и я ничего не знаю об ASM. Вот код ниже, и я поставил два сообщения об ошибках на линиях, которые терпят неудачу ...Код Delphi/ASM несовместим с 64-битным?

// Copy a pixel from source to dest and Swap the RGB color values 
procedure CopySwapPixel(const Source, Destination: Pointer); 
asm 
    push ebx //[DCC Error]: E2116 Invalid combination of opcode and operands 
    mov bl,[eax+0] 
    mov bh,[eax+1] 
    mov [edx+2],bl 
    mov [edx+1],bh 
    mov bl,[eax+2] 
    mov bh,[eax+3] 
    mov [edx+0],bl 
    mov [edx+3],bh 
    pop ebx //[DCC Error]: E2116 Invalid combination of opcode and operands 
end; 
+0

Вам нужно будет написать 64-битную версию ваших инструкций ASM, и используйте '{$ IFDEF WIN64}', чтобы сообщить компилятору, какой набор инструкций ASM использовать для данной целевой платформы. – LaKraven

+0

Спасибо, но ключ в том, что я ничего не знаю о ASM, чтобы знать, как его написать. –

+0

Нашел что-то здесь: http://docwiki.embarcadero.com/RADStudio/en/Converting_32-bit_Delphi_Applications_to_64-bit_Windows - он говорит, что «asm не поддерживается в 64-битном XE2» –

ответ

12

Эта процедура меняет порядок байтов ABGR в ARGB и наоборот.
В 32-х этот код должен делать всю работу:

mov ecx, [eax] //ABGR from src 
bswap ecx  //RGBA 
ror ecx, 8  //ARGB 
mov [edx], ecx //to dest 

Правильный код X64 является

mov ecx, [rcx] //ABGR from src 
bswap ecx  //RGBA 
ror ecx, 8  //ARGB 
mov [rdx], ecx //to dest 

Еще один вариант - сделать чистый Pascal версии, которая изменяет порядок байтов в виде массива:- 2103 (обмен 0-го и 2-го байтов).

procedure Swp(const Source, Destination: Pointer); 
var 
    s, d: PByteArray; 
begin 
    s := PByteArray(Source); 
    d := PByteArray(Destination); 
    d[0] := s[2]; 
    d[1] := s[1]; 
    d[2] := s[0]; 
    d[3] := s[3]; 
end; 
+1

Версия asm не будет работать в 64 бит, как вы заявили. Лучший вариант - использовать pascal. Для лучшей производительности выполните эту процедуру 'inline' и не используйте временные переменные, но напрямую измените подпись на« Source, Destination: PByteArray ». +1 во всех случаях для гораздо лучшего x86 asm кодирования, чем ужасный исходный код asm (медленнее, чем pascal). Если мой поезд не был поздно этим утром, я бы поставил аналогичную версию (используя eax вместо ecx, может быть немного быстрее). Во всех случаях наилучшая производительность будет заключаться в разворачивании цикла и использовании инструкций SSE2. –

+0

PS - 4 линии ASM выше действительно работают, но я все равно пошел с версией pascal для удобства личной читаемости и понимания: D –

+0

@ Arnaud Bouchez BDS2006 компилятор не использует реальные временные переменные и делает всю работу в реестрах , Но вы правы в целом. И идея SSE может быть полезна, потому что это преобразование типично для обработки объемных данных. – MBo

3

У 64-разрядного бита есть разные названия для регистров указателей, и передается разница. Первые четыре параметра встроенные функции на ассемблере передаются через RCX, RDX, R8 и R9 соответственно

EBX -> RBX 
EAX -> RAX 
EDX -> RDX 

попробовать это

procedure CopySwapPixel(const Source, Destination: Pointer); 
{$IFDEF CPUX64} 
asm 
    mov al,[rcx+0] 
    mov ah,[rcx+1] 
    mov [rdx+2],al 
    mov [rdx+1],ah 
    mov al,[rcx+2] 
    mov ah,[rcx+3] 
    mov [rdx+0],al 
    mov [rdx+3],ah 
end; 
{$ELSE} 
asm 
    push ebx //[DCC Error]: E2116 Invalid combination of opcode and operands 
    mov bl,[eax+0] 
    mov bh,[eax+1] 
    mov [edx+2],bl 
    mov [edx+1],bh 
    mov bl,[eax+2] 
    mov bh,[eax+3] 
    mov [edx+0],bl 
    mov [edx+3],bh 
    pop ebx //[DCC Error]: E2116 Invalid combination of opcode and operands 
end; 
{$ENDIF} 
+0

Я подозреваю, что компилятору x64 не понравится этот код asm. Вам нужно указать, что в этой процедуре asm не требуется фрейм стека (в начале блока 'asm ... end' требуется инструкция псевдо-компилятора' .noframe'. И это будет не быстрее, чем чистый паскаль. Поэтому IMHO следует рекомендовать версию с чистым паскалем. Он также будет готов к ARM для вашего следующего приложения для iPhone (или Android?). ;) –

+1

@arnoud bouchez: если вы используете только asm..end (так без начала), то стековый фрейм уже опускается. И поскольку у руки большой эндиан, вероятно, нет необходимости вообще меняться ;-) – Remko

+1

.noframe - это просто способ помочь компилятору пропустить инструкции по генерации стека для прохождения параметров; он не имеет ничего общего с компиляцией или компиляцией. Для 64 бит вы не можете перетащить 32-битный регистр в стек так же, как 32 бита, вы не можете нажать 16 регистров (AX, DX ...) для стека. Если он изменится, чтобы нажать RBX, он будет скомпилирован под 64-битным компилятором, но эти коды asm не верны. – APZ28