Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »
Страницы: 1 2 3

Асм в FPC


dmk ©   (14.02.17 20:34

Привет!

Ассемблер странный какой-то в FPC. Совсем с Delphi не совместим.
Если у Delphi переменная и есть смещение, то в FPC надо rip подставить + смещение. Это верно или есть другие возможности?
Нужно загрузить dqword из памяти в регистр.

procedure BlendDataScLineSSSE3(sA, dA: TAddress; dLen: dword; dOpacity: byte);
const
 PExtractAlpha: UInt128 = ($0100010001000100, $0100010001000100); //Для формирования маски умножения Alpha и lpADif
 PQuadAlpha1: UInt128 = ($FF03FF03FF03FF03, $FF07FF07FF07FF07); //Для формирования маски умножения Alpha и lpADif
 PExtractPixel: UInt128 = ($FF03FF02FF01FF00, $FF07FF06FF05FF04); //Формирование маски исходного пиксела
 PClearMask: UInt128 = ($FFFFFFFFFFFFFFFF, $FFFFFFFFFFFFFFFF); //Маска очистки

asm
 xor r10, r10
 mov r10d, dLen //Кол-во пикселей
 movzx r11, r10b //В r11 будет хранится остаток
 shr r10d, 2 //Читаем по 4 пиксела
 and r11, 03h //Сохраняем первые 3 бита, чтобы найти остаток

 mov r8, dA //Адрес назначения

 movdqu xmm6, [rip + PExtractAlpha] //Формирование маски умножения
 movdqu xmm7, [rip + PExtractPixel] //Формирование маски умножения

 test r10, r10 //Проверка на ноль
 jz @@CheckCounter //Quad-пикселов нет

 //Формируем маски очистки из одной
 movdqu xmm12, [rip + PClearMask] //Читаем общую маску очистки
 movdqu xmm8, xmm12 //Для создания маски инверсии
 psrlw xmm8, 8 //Создаем маску инверсии
 psrldq xmm12, 8 //в xmm12 маска очистки 7..0 байтов

 movdqu xmm11, [rip + PQuadAlpha1] //Маска извлечения альфы для первых двух пикселов
 movdqu xmm9, xmm6//PAddOne //Для прибавления единицы
 psrlw xmm9, 8 //Получаем маску прибавления единицы

 movzx r9d, dOpacity //Прозрачность dOpacity
 movd xmm13, r9d
 pshufb xmm13, xmm6 //Транслируем маску прозрачности в слова


dmk ©   (14.02.17 20:50[1]

Или вот например, такой код под Delphi идет на ура, а в FPC уже не работает.
Хотя компилируется замечательно и ошибок не выдает.


function TRegion.PtInRegion(x, y: integer): boolean;
asm
 cmp x, self.rEX
 ja @@Out
 cmp x, self.rX
 jl @@Out
 cmp y, self.rEY
 ja @@Out
 cmp y, self.rY
 jl @@Out
 mov al, 01h
 ret

@@Out:
 xor al, al
end;


NoUser ©   (14.02.17 21:17[2]

dmk, извини, но зачем тебе асм, эсли ты его знать/учить не хочешь?


dmk ©   (14.02.17 21:51[3]

Под Delphi работает, под FPC нет. Что не так?
А учительствовать не нужно. Нет желания пояснить, то лучше мимо проходите.
Не все бегать могут, но ноги же им нужны :)


dmk ©   (14.02.17 21:55[4]

Не то, чтобы я его совсем не знал. У меня очень много на ассемблере написано. Огромное большинство работает без проблем. Проблемы возникли только с self под FPC. Но ведь это особенности языка и передачи параметров. Правильно?


NoUser ©   (14.02.17 22:19[5]

Но ведь это особенности языка - какого? ))

У меня очень много на ассемблере
значит поставить bp и посмотреть disasm не проблема?


dmk ©   (14.02.17 23:00[6]

>значит поставить bp и посмотреть disasm не проблема?
Проблема. В Lazarus нет такого отладочного окна как в Delphi.


NoUser ©   (15.02.17 00:53[7]

Есть,
Сtrl+Alt+D
Сtrl+Alt+R
...


dmk ©   (15.02.17 07:14[8]

Ну вот, реальная помощь. Глаз уже замылился. Не нашел с первого раза.
Спасибо!


Rouse_ ©   (15.02.17 09:30[9]

RIP?  Это что за чудеса такие?
А если, к примеру:

lea rax, PExtractAlpha
movdqu xmm7, [rax]

Так работать будет?


dmk ©   (15.02.17 09:33[10]

Код из [1] абсолютно правильный. Ошибок нет. Но работать в FPC он не хочет. Почему не понятно. Все версии на Delphi работают без проблем.

function TRegion.PtInRegion(x, y: integer): boolean;
{begin
 if (x >= rX) and (x <= rEX) then result := (y >= rY) and (y <= rEY) else result := false;
end;}
asm
 mov rcx, self
 cmp x, [rcx + intEX]
 ja @Ex
 cmp x, [rcx + intX]
 jl @Ex
 cmp y, [rcx + intEY]
 ja @Ex
 cmp y, [rcx + intY]
 jl @Ex
 mov rax, true
 ret

@Ex:
 mov rax, false
end;


На Delphi работает, в FPC нет. Байт коды от Delphi скормить не удалось.
и такая не работает:

function TRegion.PtInRegion(x, y: integer): boolean;
{begin
 if (x >= rX) and (x <= rEX) then result := (y >= rY) and (y <= rEY) else result := false;
end;}
asm
 mov ecx, self
 mov eax, [ecx + intEX]
 cmp x, eax
 ja @Ex
 mov eax,  [ecx + intX]
 cmp x, eax
 jl @Ex
 mov eax,  [ecx + intEY]
 cmp y, eax
 ja @Ex
 mov eax,  [ecx + intY]
 cmp y, eax
 jl @Ex
 mov rax, $01
 ret

@Ex:
 mov rax, $00
end;


dmk ©   (15.02.17 09:52[11]

Rouse_ ©   (15.02.17 09:30) [9]

Не работает. Один раз пропустил почему-то но выдал ерунду. Второй раз не получилось.

с MMX то же самое. rip + хочет.

procedure BlendDataScLineMMX(sA, dA: TAddress; dLen: dword; dOpacity: byte);
const
 ShufMask: uint64 = $0100010001000100;

asm
 xor r10, r10
 mov r10d, dLen

 movq mm6, [rip + ShufMask] //Формирование маски умножения
 mov r8, dA //Адрес назначения    


dmk ©   (15.02.17 10:05[12]

У  FPC 3.0.0. какие то проблемы с выравниванием. В гугле ничего не нашел кроме rip.
Хотя movdqu - это невыровненная ячейка, а movdqa - с выравниванием.
Не знаю. В Дельфи работает, в FPC - хрень. Надо разбираться.


Rouse_ ©   (15.02.17 10:10[13]

Очистранно, нука скинь свой пример на rouse@grandsmeta.ru в виде проекта, доберусь до работы попробую пошаманить, ты лазарус используешь ведь?


Rouse_ ©   (15.02.17 12:28[14]

Короче проверил, все работает, но есть нюансы с эпилогом асм функций. Пролог выставляется автоматом и ты его не учитываешь, поэтому падает:

unit Unit1;

{$mode objfpc}{$H+}
{$ASMMODE INTEL}

interface

uses
 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

type

 { TForm1 }

 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
 private
   { private declarations }
 public
   { public declarations }
 end;

 { TRegion }

 TRegion = class
 public
   rEX, rX, rEY, rY: Cardinal;
   function PtInRegion(x, y: integer): boolean; assembler;
 end;

var
 Form1: TForm1;

implementation

{$R *.lfm}

{ TRegion }

function TRegion.PtInRegion(x, y: integer): boolean;
asm
// здесь эпилог, жрет 8 байт стека, которые нужно вернуть в EBP чтобы RET выполнился
cmp x, self.rEX
ja @@Out
cmp x, self.rX
jl @@Out
cmp y, self.rEY
ja @@Out
cmp y, self.rY
jl @@Out
mov al, 01h

// не выпендриваясь делаем эпилог ручками
pop ebp
pop ebp

ret

@@Out:
xor al, al

// не выпендриваясь делаем эпилог ручками
pop ebp
pop ebp

ret
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
 R: TRegion;
begin
 R := TRegion.Create;
 R.rEX := 100;
 R.rEY := 100;
 R.rX  := 0;
 R.rY  := 0;
 ShowMessage(BoolToStr(R.PtInRegion(50, 50), True));
end;

end.
     


Rouse_ ©   (15.02.17 12:29[15]

А... про загрузку забыл, щас тоже проверю


Rouse_ ©   (15.02.17 13:06[16]

Мдя, действительно, RIP нужен

lea rax, PExtractAlpha
movdqu xmm6, [rax]

movdqu xmm6, [PExtractAlpha]

movdqu xmm6, [rip + PExtractAlpha]


кодируется как:

000000010002C439 | 48 8D 04 25 70 A4 18 00  | lea rax,qword ptr ds:[18A470]
000000010002C441 | F3 0F 6F 30              | movdqu xmm6,dqword ptr ds:[rax]        

000000010002C445 | F3 0F 6F 34 25 70 A4 18  | movdqu xmm6,dqword ptr ds:[18A470]

000000010002C44E | F3 0F 6F 35 1A E0 15 00  | movdqu xmm6,dqword ptr ds:[10018A468]


dmk ©   (15.02.17 13:34[17]

// не выпендриваясь делаем эпилог ручками
pop ebp
pop ebp

Так это 32 бита. У меня — 64 :) Под 64 не пашет.
У меня вот что генерит:

Region64.pas:304                          asm
0000000100042940 488d6424f8               lea    -0x8(%rsp),%rsp
Region64.pas:305                          cmp x, self.rEX
0000000100042945 3b5108                   cmp    0x8(%rcx),%edx
Region64.pas:306                          ja @@Out
0000000100042948 7713                     ja     0x10004295d <PTINREGION+29>
Region64.pas:307                          cmp x, self.rX
000000010004294A 39ca                     cmp    %ecx,%edx
Region64.pas:308                          jl @@Out
000000010004294C 7c0f                     jl     0x10004295d <PTINREGION+29>
Region64.pas:309                          cmp y, self.rEY
000000010004294E 443b410c                 cmp    0xc(%rcx),%r8d
Region64.pas:310                          ja @@Out
0000000100042952 7709                     ja     0x10004295d <PTINREGION+29>
Region64.pas:311                          cmp y, self.rY
0000000100042954 443b4104                 cmp    0x4(%rcx),%r8d
Region64.pas:312                          jl @@Out
0000000100042958 7c03                     jl     0x10004295d <PTINREGION+29>
Region64.pas:313                          mov al, 01h
000000010004295A b001                     mov    $0x1,%al
Region64.pas:314                          ret
000000010004295C c3                       retq  
Region64.pas:317                          xor al, al
000000010004295D 30c0                     xor    %al,%al
Region64.pas:318                          end;
000000010004295F 488d642408               lea    0x8(%rsp),%rsp
0000000100042964 c30000000000000000000000 retq  


Rouse_ ©   (15.02.17 13:46[18]

Ну блин, я ж тебе направление даже подсказал, чего сам не перепроверишь? :)

Ня, тот-же стек, только немного больше уплывший под 64 - отладчик возьми в руки.

function TRegion.PtInRegion(x, y: integer): boolean;
asm
// здесь эпилог, жрет 8 байт стека, которые нужно вернуть в EBP чтобы RET выполнился
cmp x, self.rEX
ja @@Out
cmp x, self.rX
jl @@Out
cmp y, self.rEY
ja @@Out
cmp y, self.rY
jl @@Out
mov al, 01h

// не выпендриваясь делаем эпилог ручками
pop rbp
pop rbp
pop rbp

ret

@@Out:
xor al, al

// не выпендриваясь делаем эпилог ручками
pop rbp
pop rbp
pop rbp

ret
end
;


Rouse_ ©   (15.02.17 13:53[19]

на, вот еще советую нормальный отладчик. а то от лазарусного у меня чуть крыша не сдвинулась с его выхлопом: http://x64dbg.com/


Страницы: 1 2 3 версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо