-
Я так понял, что ANDN (Logical AND NOT) инструкция не поддерживается Delphi? У меня XE6. Компилятор говорит Undeclared identifier.
-
нет конечно, ибо BMI1. (как и TZCNT) Она практически никакими декомпилерами не поддерживается. А AND + NOT использовать не судьба?
-
blsr, blsi, blsmsk тоже не поддерживает :( короче инструкции bmi1 и dmi2 в Delphi отсутствуют.
-
>А AND + NOT использовать не судьба? Мне байт надо превратить в 64 бита. Не знаю как лучше сделать. короче есть байт 10101111b, а нужно из него сделать FF00FF00FFFFFFFFh У меня сейчас таблица зарнее расчитана 8 -> 64, но очень медленно получается из памяти читать.
-
Сейчас через таблицу[0..255] работает:
mov rdx, TableAddr movzx eax, byte ptr [rsi] shl ax, 3 //Смещение в таблице mov rax, [rdx+rax] //Читаем строку байтов mov [rdi], rax //Пишем готовую строку
Думал быстрее сделать.
-
> dmk © (20.02.17 10:16) [4]
Чет я слегка прифигел, нукась дай ка мне саму таблицу.
-
По описанию вроде bextr подходит, но она тоже bmi1 :(
-
Таблица расчитывается. Так не выложишь ;)
//Процедура создает массив отображающий биты в Grayscale представлении //Пример: (10001111) = ($00 $FF $FF $FF $00 $00 $00 $00) //Используется для прорисовки при битности 1 Bpp //Массив занимает 1Кб procedure InitGrayBits; var i: byte; //Счетчик байтов bc: byte; //Счетчик битов
begin for i := 0 to 255 do for bc := 0 to 7 do if GetBit(i, bc) then //Если бит установлен, то это черный цвет //Если не установлен, то прозрачная область, т.е. белый GrayBitsArray[i].Cell[7 - bc] := $00 else GrayBitsArray[i].Cell[7 - bc] := $FF;
//Адрес начала массива GrayBitsAddr := TAddress(@GrayBitsArray[0].Cell[0]); end;
-
Вернее таблица занимает 2Кб
-
Вот чесно говоря ничего не понятно :) Покажи процедуру с асмом полностью, ибо вот после этого:
movzx eax, byte ptr [rsi] ... mov rax, [rdx+rax] //Читаем строку байтов без xor rax, rax имеешь шанс вылететь в трубу
еще не понятно откуда RSI приходит
-
хотя нет, про RAX это лишнее
-
Преобразует биты в байты: GrayBitsAddr - это таблица
procedure BitsToBytes(Src, Dest, NumBits: uint64); asm .NOFRAME movq xmm0, rsi movq xmm1, rdi movq xmm2, rbx
mov rdi, Dest //Адрес конечного буфера
mov bl, Self.FIndexedMask mov rsi, Src //Адрес изображения mov rcx, NumBits //Кол-во бит для преобразования shr rcx, 3 //Делим на 8, т.к. читаем байты mov rdx, GrayBitsAddr //Массив Gray-представления битов mov r9, $FFFFFFFFFFFFFFFF xor rax, rax //Очистка
cmp bl, 0 je @@ClearMask
@@NextByte: movzx eax, byte ptr [rsi] //Читаем байт изображения, или 8 Bitmap пикселей test al, al jz @@WriteWhite
shl ax, 3 //Смещение в массиве GrayBits к нужной ячейке mov rax, [rdx+rax] //Читаем строку байтов из GrayBits в rax mov [rdi], rax //Пишем строку в конечный адрес jmp @@NextAddr
@@WriteWhite: mov [rdi], r9 //Пишем нулевую строку в конечный адрес
@@NextAddr: inc rsi //Смещение к следующему исходному байту изображения add rdi, 8 //Смещение в конечном адресе на 8 байт dec rcx jnz @@NextByte
jmp @@Out
@@ClearMask: //Каналы отключены, пишем нулевые пикселы mov [rdi], r9 //Пишем строку в конечный адрес add rdi, 8 dec rcx jnz @@ClearMask
@@Out: movq rbx, xmm2 movq rdi, xmm1 movq rsi, xmm0 end;
-
Ну в принципе норм. только вот так бы вот начало переписал:
procedure BitsToBytes(Src, Dest, NumBits: uint64); asm .NOFRAME movq xmm0, rsi movq xmm1, rdi movq xmm2, rbx mov rdi, Dest //Адрес конечного буфера xor rax, rax //Очистка mov bl, Self.FIndexedMask mov r9, $FFFFFFFFFFFFFFFF mov rcx, NumBits //Кол-во бит для преобразования shr rcx, 3 //Делим на 8, т.к. читаем байты cmp bl, 0 je @@ClearMask mov rsi, Src //Адрес изображения mov rdx, GrayBitsAddr //Массив Gray-представления битов
-
а, блин, за вот такое руки бы оторвать: movq xmm0, rsi movq xmm1, rdi movq xmm2, rbx
у тебя чего стека нема? А если у меня там Extended лежит промежуточный?
-
Не, там ничего не лежит. Со стеком медленнее работает. Память все таки.
Есть такой вариант, но он медленнее в 2 раза.
procedure TImageStream.BitsToBytesShuf(Src, Dest, NumBits: uint64); const ShufMask: uint64 = $00000000000000FF;
asm .NOFRAME movq xmm0, rsi movq xmm1, rdi movq xmm2, rbx
mov rdi, Dest //Адрес конечного буфера
mov r10b, Self.FIndexedMask mov rsi, Src //Адрес изображения mov rcx, NumBits //Кол-во бит для преобразования shr rcx, 3 //Делим на 8, т.к. читаем байты mov rdx, 8 movq xmm4, ShufMask movq xmm5, xmm4
@@NextByte: movzx rax, byte ptr [rsi] //Читаем байт изображения, или 8 Bitmap пикселей and al, r10b
bt ax, 0 setc bl shl rbx, 8
bt ax, 1 setc bl shl rbx, 8
bt ax, 2 setc bl shl rbx, 8
bt ax, 3 setc bl shl rbx, 8
bt ax, 4 setc bl shl rbx, 8
bt ax, 5 setc bl shl rbx, 8
bt ax, 6 setc bl shl rbx, 8
bt ax, 7 setc bl
movq xmm3, rbx movq xmm4, xmm5 pshufb xmm4, xmm3 movq [rdi], xmm4 //Пишем строку в конечный адрес
inc rsi //Смещение к следующему исходному байту изображения add rdi, rdx //Смещение в конечном адресе на 8 байт dec rcx jnz @@NextByte
@@Out: movq rbx, xmm2 movq rdi, xmm1 movq rsi, xmm0 end;
-
>А если у меня там Extended лежит промежуточный?
In line with the x64 Application Binary Interface (ABI), the contents of the following registers must be preserved and restored within inline assembly functions: R12, R13, R14, R15, RDI, RSI, RBX, RBP, RSP, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15.
Уже проверял. xmm0-xmm3 всегда свободны. Потому и использую как стек. Быстрее все рабоатет.
-
имбаркадеро вообще память копирует через FPU. Ничего - работает :)
-
Да, это я уже заработался, у меня половина защиты через XMM и DR регистры выстроена. Ошибся.
-
Интересно, а как собрать самому последовательность?
Кое что прочитал, но пока не понял как инструкцию собрать ;(
//Наследственные префиксы 66H, 67H, F2H and F3H. //Используются для новых инструкций //Размещаются перед REX префиксом
//1 bit w Определяет данные как байт или полноразмерные, где полноразмерные это 16 или 32 бита (Таблица B-6) //1 bit s Определяет знак поля данных (see Table B-7) //2 bit sreg2 Segment register specifier for CS, SS, DS, ES (see Table B-8) //3 bit sreg3 Segment register specifier for CS, SS, DS, ES, FS, GS (see Table B-8) //3 bit eee Specifies a special-purpose (control or debug) register (Таблица B-9) //4 bit tttn Для условных инструкций определяет состояние ASSERTED (Утвержденный) или NEGATED (Отрицается) (Таблица B-12) //1 bit d Определяет направление операции (Таблица B-11)
//REX префикс (Mod Reg* R/M) - 1 байт //7-6 Mod //5-3 Reg //2-0 R/M
//SIB 1 байт //7-6 Scale //5-3 Index //2-0 Base
//Поле reg (3 бита) Определитель основных регистров (Таблица B-4 или B-5) для инструкций не содержащих поле W //000 AX | EAX | RAX //001 CX | ECX | RCX //010 DX | EDX | RDX //011 BX | EBX | RBX //100 SP | ESP | RSP //101 BP | EBP | RBP //110 SI | ESI | RSI //111 DI | EDI | RDI
REX W RXB W MOD REG R/M 0100 1 100 1000 1001 11 000 010 REX W RXB RAX RDX 0100 1 000 1000 1001 11 010 011 RDX RBX
-
ну как в обычном ассемблирующем движке, у тебя даже REX префикс обозначен
|