Конференция "FreePascal" » Асм в FPC
 
  • dmk © (14.02.17 20:34) [0]
    Привет!

    Ассемблер странный какой-то в 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/
 
Конференция "FreePascal" » Асм в FPC
Есть новые Нет новых   [118640   +43][b:0][p:0.002]