mã máy x86-64 (và x86-32), 13 15 13 byte
thay đổi:
Sửa lỗi: phiên bản đầu tiên chỉ kiểm tra G = 0xff, không yêu cầu R và B là 0. Tôi đã thay đổi để sửa đổi nền tại chỗ để tôi có thể sử dụng lodsd
trên nền trước để có pixel fg eax
cho cmp eax, imm32
mã hóa dạng ngắn (5 byte ), thay vì cmp dh,0xff
(3 byte).
Lưu 2 byte: nhận thấy rằng sửa đổi bg tại chỗ được phép sử dụng toán hạng bộ nhớ cho cmov
, lưu mov
tải 2 byte (và lưu một thanh ghi, trong trường hợp có vấn đề).
Đây là một chức năng theo quy ước gọi System V x86-64, có thể gọi trực tiếp từ C hoặc C ++ (trên các hệ thống không phải Windows x86-64) với chữ ký này:
void chromakey_blend_RGB32(uint32_t *background /*rdi*/,
const uint32_t *foreground /*rsi*/,
int dummy, size_t pixel_count /*rcx*/);
Định dạng hình ảnh là RGB0 32bpp, với thành phần màu xanh lá cây ở địa chỉ bộ nhớ thấp thứ 2 trong mỗi pixel. Các nền nền trước được sửa đổi tại chỗ. pixel_count
là hàng * cột. Nó không quan tâm đến hàng / cột; nó chỉ là chromekey pha trộn tuy nhiên nhiều từ khóa của bộ nhớ mà bạn chỉ định.
RGBA (với A được yêu cầu là 0xFF) sẽ yêu cầu sử dụng hằng số khác nhau, nhưng không thay đổi kích thước chức năng. Các DWORD tiền cảnh được so sánh về sự bằng nhau chính xác so với hằng số 32 bit tùy ý được lưu trữ trong 4 byte, do đó, có thể dễ dàng hỗ trợ bất kỳ màu nào theo thứ tự pixel hoặc màu sắc của phím màu.
Mã máy tương tự cũng hoạt động ở chế độ 32 bit. Để lắp ráp thành 32 bit, thay đổirdi
thành edi
trong nguồn. Tất cả các thanh ghi khác trở thành 64 bit đều ẩn (lodsd / stosd và loop), và các reg rõ ràng khác ở lại 32 bit. Nhưng lưu ý rằng bạn sẽ cần một trình bao bọc để gọi từ C 32 bit, vì không có quy ước gọi x86-32 tiêu chuẩn nào sử dụng các regs tương tự như x86-64 SysV.
Danh sách NASM (mã máy + mã nguồn), được nhận xét cho người mới bắt đầu với mô tả về những gì các hướng dẫn phức tạp hơn làm. (Sao chép hướng dẫn tham khảo hướng dẫn là phong cách xấu trong sử dụng bình thường.)
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
Để lấy nguồn NASM ban đầu ra khỏi danh sách này, hãy loại bỏ 26 ký tự hàng đầu của mỗi dòng <chromakey.lst cut -b 26- > chromakey.asm
. Tôi đã tạo điều này với
nasm -felf64 chromakey-blend.asm -l /dev/stdout | cut -b -28,$((28+12))-
danh sách NASM để lại nhiều cột trống hơn tôi muốn giữa mã máy và nguồn. Để xây dựng một tệp đối tượng, bạn có thể liên kết với C hoặc C ++, sử dụng nasm -felf64 chromakey.asm
. (Hoặc làyasm -felf64 chromakey.asm
).
chưa được kiểm tra , nhưng tôi khá tự tin rằng ý tưởng cơ bản về tải / tải / cmov / cửa hàng là âm thanh, bởi vì nó rất đơn giản.
Tôi có thể lưu 3 byte nếu tôi có thể yêu cầu người gọi vượt qua hằng số khóa sắc độ (0x00ff00) như một đối số phụ, thay vì mã hóa cứng hằng số vào hàm. Tôi không nghĩ rằng các quy tắc thông thường cho phép viết một hàm chung hơn có người gọi thiết lập các hằng số cho nó. Nhưng nếu có, arg thứ 3 (hiện tại dummy
) được truyền vào edx
trong x86-64 SysV ABI. Chỉ cần thay đổi cmp eax, 0x0000ff00
(5B) thành cmp eax, edx
(2B).
Với SSE4 hoặc AVX, bạn có thể thực hiện việc này nhanh hơn (nhưng kích thước mã lớn hơn) pcmpeqd
và blendvps
để thực hiện pha trộn biến kích thước phần tử 32 bit được điều khiển bởi mặt nạ so sánh. (Với pand
, bạn có thể bỏ qua byte cao). Đối với RGB24 được đóng gói, bạn có thể sử dụng pcmpeqb
và sau đó là 2x pshufb
+ pand
để lấy TRUE theo byte trong đó cả 3 thành phần của pixel đó khớp với nhau pblendvb
.
(Tôi biết đây là môn đánh gôn, nhưng tôi đã xem xét thử MMX trước khi đi với số nguyên vô hướng.)