快速内存比较函数CompareMem(Delphi SSE优化算法应用之二)

 

function CGCompareMem(P1, P2: Pointer; Length: Integer): Integer; assembler;
asm
        PUSH    ESI
        PUSH    EDI
        PUSH    ECX
        PUSH    EBX
        MOV     ESI,P1
        MOV     EDI,P2
        CMP     ESI,EDI
        JZ      @Equal
        CMP     ECX,1 
        JL      @NotEqual
        MOV     edx,ecx
        shr     edx, 4 
        and     ecx, 15 
        test    ecx,ecx
        JZ      @SSECMP2
        mov     eax,-16
        sub     esi,eax
        sub     edi,eax
@CompareLoop:
        mov     ebx, [ESI + Eax]
        xor     ebx, [EDI + Eax]
        jnz     @Mismatch
        add     Eax, 4
        js      @CompareLoop
        JMP     @SSECMP
@Mismatch:
        bsf      ebx, ebx
        shr      ebx, 3
        sub      eax,-16
        add      eax,ebx
        add      eax,1
        JMP      @EXIT
@SSECMP:
        sub     esi,16
        sub     edi,16
@SSECMP2:
        TEST    edx,edx
        JZ      @EXIT
        mov     eax,ecx
        neg     edx
        pxor    xmm2,xmm2
@SSECMPLOOP:
        movups  xmm0,[ESI + Eax]
        movups  xmm1,[EDI + Eax]
        pxor    xmm0,  xmm1
        pcmpeqb  xmm0, xmm2
        pmovmskb ebx, xmm0
        CMP     ebx,$FFFF
        jnz     @SSEMismatch
        add     eax,16
        inc     edx
        js      @SSECMPLOOP
        xor     eax,eax
        JMP     @EXIT

@SSEMismatch:
        mov     ebx, [ESI + Eax]
        xor     ebx, [EDI + Eax]
        jnz     @Mismatch2
        add     Eax, 4
        jmp     @SSEMismatch
@Mismatch2:
       bsf      ebx, ebx
       shr      ebx, 3
       add      eax,ebx
       add      eax,1
       JMP     @EXIT
@NotEqual:
        MOV     EAX,-1
        JMP     @EXIT
@Equal:
        XOR     EAX,EAX
@EXIT:
        POP     EBX
        POP     ECX
        POP     EDI
        POP     ESI
end;

经测试比常规算法快60%-110%

要在 Delphi 7 中找到指定窗口中的图片并单击它,可以使用以下代码: ```delphi uses Windows, Messages, Graphics; function FindBitmap(hWnd: HWND; Bitmap: TBitmap): TPoint; var DC: HDC; Rect: TRect; BitmapDC: HDC; BitmapSize: TSize; BitmapBits: Pointer; BitmapInfo: BITMAPINFO; begin Result := Point(-1, -1); // 获取窗口的设备上下文,以便进行截图 DC := GetDC(hWnd); try // 获取窗口的客户区域 GetClientRect(hWnd, Rect); // 创建一个和窗口客户区域大小相同的位图 BitmapDC := CreateCompatibleDC(DC); try Bitmap.Width := Rect.Width; Bitmap.Height := Rect.Height; SelectObject(BitmapDC, Bitmap.Handle); // 将窗口的内容绘制到位图中 BitBlt(BitmapDC, 0, 0, Bitmap.Width, Bitmap.Height, DC, Rect.Left, Rect.Top, SRCCOPY); // 获取位图信息 FillChar(BitmapInfo, SizeOf(BitmapInfo), 0); BitmapInfo.bmiHeader.biSize := SizeOf(BitmapInfo.bmiHeader); BitmapInfo.bmiHeader.biWidth := Bitmap.Width; BitmapInfo.bmiHeader.biHeight := -Bitmap.Height; // 注意这里要取反,因为位图是从上到下的 BitmapInfo.bmiHeader.biPlanes := 1; BitmapInfo.bmiHeader.biBitCount := 24; // 假设位图是 24 位色彩 // 获取位图数据的指针 BitmapBits := Bitmap.ScanLine[0]; // 在位图中搜索目标位图,并返回其位置 // 这里可以使用各种算法,比如暴力匹配、KMP 算法、Boyer-Moore 算法等等 // 为了简单起见,这里只是遍历整个位图 BitmapSize.cx := Bitmap.Width; BitmapSize.cy := Bitmap.Height; for var I := 0 to BitmapSize.cy - 1 do begin for var J := 0 to BitmapSize.cx - 1 do begin if CompareMem(Pointer(NativeInt(BitmapBits) + I * Bitmap.Width * 3 + J * 3), Bitmap.ScanLine[0], Bitmap.Height * Bitmap.Width * 3) then begin Result.X := J; Result.Y := I; Exit; end; end; end; finally DeleteDC(BitmapDC); end; finally ReleaseDC(hWnd, DC); end; end; procedure ClickBitmap(hWnd: HWND; Bitmap: TBitmap); var Pos: TPoint; begin // 查找位图在窗口中的位置 Pos := FindBitmap(hWnd, Bitmap); if (Pos.X >= 0) and (Pos.Y >= 0) then begin // 计算位图的中心点位置 Pos.X := Pos.X + Bitmap.Width div 2; Pos.Y := Pos.Y + Bitmap.Height div 2; // 将屏幕坐标转换为窗口客户区坐标 ScreenToClient(hWnd, Pos); // 发送鼠标单击事件 SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, Pos.X or (Pos.Y shl 16)); SendMessage(hWnd, WM_LBUTTONUP, 0, Pos.X or (Pos.Y shl 16)); end; end; ``` 这段代码定义了两个函数,`FindBitmap` 和 `ClickBitmap`。`FindBitmap` 函数用于在指定窗口中查找目标位图,并返回其位置。`ClickBitmap` 函数用于在指定窗口中单击目标位图。 你只需要将目标位图加载到 `TBitmap` 对象中,然后调用 `ClickBitmap` 函数即可。 注意,这段代码只是演示了如何在窗口中查找目标位图,并单击它。具体实现方式可能因不同的应用场景而有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值