Kod maszynowy x86-64 (i x86-32), 13 15 13 bajtów
dziennik zmian:
Bugfix: pierwsza wersja sprawdzała tylko G = 0xff, nie wymagając, aby R i B wynosiły 0. Zmieniłem na modyfikację tła w miejscu, dzięki czemu mogłem użyć lodsd
na pierwszym planie, aby mieć piksele fg eax
do cmp eax, imm32
kodowania krótkiego (5 bajtów ), zamiast cmp dh,0xff
(3 bajty).
Zapisz 2 bajty: zauważyłem, że modyfikacja bg w miejscu pozwoliła na użycie operandu pamięci cmov
, zapisanie 2-bajtowego mov
obciążenia (i zapisanie rejestru, w razie potrzeby ).
Jest to funkcja zgodna z konwencją wywoływania Systemu V x86-64, wywoływaną bezpośrednio z C lub C ++ (w systemach innych niż Windows x86-64) z tym podpisem:
void chromakey_blend_RGB32(uint32_t *background /*rdi*/,
const uint32_t *foreground /*rsi*/,
int dummy, size_t pixel_count /*rcx*/);
Format obrazu to RGB0 32 bpp, z zielonym składnikiem pod drugim najniższym adresem pamięci w każdym pikselu. Obraz tła pierwszego planu jest modyfikowany na miejscu. pixel_count
to rzędy * kolumny. Nie obchodzi go wiersze / kolumny; po prostu chromekey łączy dowolną liczbę domen pamięci określoną przez użytkownika.
RGBA (z A musi być 0xFF) wymagałoby użycia innej stałej, ale bez zmiany wielkości funkcji. DWORD pierwszego planu są porównywane w celu uzyskania dokładnej równości z dowolną 32-bitową stałą zapisaną w 4 bajtach, dzięki czemu można łatwo obsługiwać dowolny rząd pikseli lub kolor klucza.
Ten sam kod maszynowy działa również w trybie 32-bitowym. Aby złożyć jako 32-bitowy, zmień rdi
na edi
na źródło. Wszystkie inne rejestry, które stają się 64-bitowe, są niejawne (lodsd / stosd i loop), a inne jawne rejestry pozostają 32-bitowe. Pamiętaj jednak, że będziesz potrzebował opakowania, aby zadzwonić z 32-bitowego C, ponieważ żadna ze standardowych konwencji wywoływania x86-32 nie używa tych samych reguł co SysV x86-64.
Lista NASM (kod maszynowy + źródło), komentowała początkujących asmów opisami tego, co robią bardziej złożone instrukcje. (Powielanie instrukcji obsługi jest normalnym użytkiem w złym stylu).
1 ;; inputs:
2 ;; Background image pointed to by RDI, RGB0 format (32bpp)
3 ;; Foreground image pointed to by RSI, RGBA or RGBx (32bpp)
4 machine ;; Pixel count in RCX
5 code global chromakey_blend_RGB32
6 bytes chromakey_blend_RGB32:
7 address .loop: ;do {
8 00000000 AD lodsd ; eax=[rsi], esi+=4. load fg++
9 00000001 3D00FF0000 cmp eax, 0x0000ff00 ; check for chromakey
10 00000006 0F4407 cmove eax, [rdi] ; eax = (fg==key) ? bg : fg
11 00000009 AB stosd ; [rdi]=eax, edi+=4. store into bg++
12 0000000A E2F4 loop .loop ;} while(--rcx)
13
14 0000000C C3 ret
## next byte starts at 0x0D, function length is 0xD = 13 bytes
Aby usunąć oryginalne źródło NASM z tej listy, usuń 26 wiodących znaków każdej linii za pomocą <chromakey.lst cut -b 26- > chromakey.asm
. Wygenerowałem to z
nasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
listami NASM, pozostawiając więcej pustych kolumn między kodem maszynowym a źródłem. Aby zbudować plik obiektowy, który można połączyć za pomocą C lub C ++, użyj nasm -felf64 chromakey.asm
. (Lub yasm -felf64 chromakey.asm
).
niesprawdzone , ale jestem całkiem pewien, że podstawowa idea load / load / cmov / store jest solidna, ponieważ jest taka prosta.
Mógłbym zapisać 3 bajty, gdybym mógł zażądać od dzwoniącego przekazania stałej klucza kluczowania (0x00ff00) jako dodatkowego argumentu zamiast stałego kodowania stałej w funkcji. Nie sądzę, aby zwykłe reguły pozwalały na pisanie bardziej ogólnej funkcji, w której osoba dzwoniąca skonfigurowała dla niej stałe. Ale jeśli tak, trzeci argument (obecnie dummy
) jest przekazywany w edx
ABI SysV x86-64. Po prostu zmień cmp eax, 0x0000ff00
(5B) na cmp eax, edx
(2B).
Z SSE4 lub AVX, można zrobić to szybciej (ale większy rozmiar kodu) z pcmpeqd
i blendvps
zrobić 32-bitowego formatu elementem zmiennym mieszankę kontrolowany przez porównanie maski. (Z pand
, możesz zignorować wysoki bajt). W przypadku spakowanego RGB24 możesz użyć, pcmpeqb
a następnie 2x pshufb
+, pand
aby uzyskać PRAWDA w bajtach, w których pasują wszystkie 3 elementy tego piksela pblendvb
.
(Wiem, że to jest golf golfowy, ale zastanawiałem się nad wypróbowaniem MMX przed przejściem na liczbę całkowitą skalarną).