?不能够访问C++中的类成员函数
,但是可以访问extern "C"函数
。
?如果调用Windows API函数
,则不需要自己清除堆栈,因为API的返回指令是RET n,会自动清除堆栈
?比如下面的例子:
???#include <windows.h>
???char szAppName[] = "API Test";
???void main()
???{
?????char szHello[] = "Hello, world!";
?????__asm
?????{
???????PUSH??MB_OK or MB_ICONINformATION
???????PUSH??OFFSET szAppName??; 全局变量用OFFSET
???????LEA?? EAX, szHello????; 局部变量用LEA
???????PUSH??EAX
???????PUSH??0
???????CALL??DWORD PTR [MessageBoxA]?? ; 注意这里,我费了好大周折才发现不是CALL MessageBoxA
?????}
???}
?一般来说,在Visual C++中使用内联汇编是为了提高速度,因此这些函数调用尽可能用C/C++写。
八、一个例子
?下面的例子是在VS.NET(即VC7)中C语言写的。先建一个工程,将下列代码放到工程中的.c文件中编译,无需作特别的设置,即可编译通过。
////////////////////////////////////////////////////////////////////////////////////////////////////
?//预处理
?#include <Windows.h>
?////////////////////////////////////////////////////////////////////////////////////////////////////
?////////////////////////////////////////////////////////////////////////////////////////////////////
?//全局变量
?HWND g_hWnd;
?HINSTANCE g_hInst;
?TCHAR szTemp[1024];
?TCHAR szAppName[] = "CRC32 Sample";
?////////////////////////////////////////////////////////////////////////////////////////////////////
?////////////////////////////////////////////////////////////////////////////////////////////////////
?//函数声明
?DWORD GetCRC32(const BYTE *pbData, int nSize);
?int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow);
?LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
?////////////////////////////////////////////////////////////////////////////////////////////////////
?////////////////////////////////////////////////////////////////////////////////////////////////////
?//主函数
?int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
?{
???MSG msg;
???WNDCLASSEX wndClassEx;
???g_hInst = hInstance;
???wndClassEx.cbSize = sizeof(WNDCLASSEX);
???wndClassEx.style = CS_VREDRAW | CS_HREDRAW;
???wndClassEx.lpfnWndProc = (WNDPROC) WindowProc;
???wndClassEx.cbClsExtra = 0;
???wndClassEx.cbWndExtra = 0;
???wndClassEx.hInstance = g_hInst;
???wndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
???wndClassEx.hCursor = LoadCursor(NULL,
IDC_ARROW);
???wndClassEx.hbrBackground = (HBRUSH) (COLOR_WINDOW);
???wndClassEx.lpszMenuName = NULL;
???wndClassEx.lpszClassName = szAppName;
???wndClassEx.hIconSm = NULL;
???RegisterClassEx(&wndClassEx);
???g_hWnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICK<I>FRame</I> | WS_MINIMIZEBOX,
?????CW_USEDEFAULT, CW_USEDEFAULT, 300, 70,
?????NULL, NULL, g_hInst, NULL);
???ShowWindow(g_hWnd, iCmdShow);
???UpdateWindow(g_hWnd);
???while (GetMessage(&msg, NULL, 0, 0))
???{
?????TranslateMessage(&msg);
?????DispatchMessage(&msg);
???}
???return ((int) msg.wParam);
?}
?////////////////////////////////////////////////////////////////////////////////////////////////////
?////////////////////////////////////////////////////////////////////////////////////////////////////
?//主窗口回调函数
?LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
?{
???switch (uMsg)
???{
???case WM_CREATE:
?????CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL | WS_OVERLAPPED,
???????7, 12, 220, 22,
???????hWnd, (HMENU)1000, g_hInst, NULL);
?????CreateWindowEx(0, "BUTTON", "&OK", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_OVERLAPPED | BS_FLAT,
???????244, 12, 40, 20,
???????hWnd, (HMENU)IDOK, g_hInst, NULL);
?????break;
???case WM_COMMAND:
?????switch (LOWORD(wParam))
?????{
?????case IDOK:
???????GetDlgItemText(g_hWnd, 1000, szTemp + 100, 800);
???????wsprintf(szTemp, "当前文本框内的字符串的CRC32校验码是: 0x%lX", GetCRC32(szTemp + 100, (int)strlen(szTemp + 100)));
???????MessageBox(g_hWnd, szTemp, szAppName, MB_OK|MB_ICONINformATION);
?????}
?????break;
???case WM_DESTROY:
?????PostQuitMessage(0);
?????break;
???default:
?????return (DefWindowProc(hWnd, uMsg, wParam, lParam));
???}
???return (0);
?}
?////////////////////////////////////////////////////////////////////////////////////////////////////
?////////////////////////////////////////////////////////////////////////////////////////////////////
?//GetCRC32: 求字节流的CRC32校验码
?//参数:
?//???pbData: 指向字节流缓冲区首地址
?//???nSize: 字节流长度
?//
?//返回值:
?//???字节流的CRC32校验码
?//
?//这里使用查表法求CRC32校验码,这部分是参考老罗的文章《 矛与盾的较量(2)——CRC原理篇》该写的。
?//
?//下面使用内联汇编求CRC32校验码,充分使用了CPU中的寄存器,速度和方便性都是使用C/C++所不能比拟的
?//
?DWORD GetCRC32(const BYTE *pbData, int nSize)
?{
???DWORD dwCRC32Table[256];
???__asm? //这片内联汇编是初始化CRC32表
???{
?????MOV?? ECX, 256
?_NextTable:
?????LEA?? EAX, [ECX-1]
?????PUSH??ECX
?????MOV?? ECX, 8
?_NextBit:
?????SHR?? EAX, 1
?????JNC?? _NotCarry
?????XOR?? EAX, 0xEDB88320
?_NotCarry:
?????DEC?? ECX
?????JNZ?? _NextBit
?????POP?? ECX
?????MOV?? [dwCRC32Table + ECX*4 - 4], EAX
?????DEC?? ECX
?????JNZ?? _NextTable
???}
???__asm? //下面是求CRC32校验码
???{
?????MOV?? EAX, -1
?????MOV?? EBX, pbData
?????OR???EBX, EBX
?????JZ???_Done
?????MOV?? ECX, nSize
?????OR???ECX, ECX
?????JZ???_Done
?_NextByte:
?????MOV?? DL, [EBX]
?????XOR?? DL, AL
?????MOVZX? EDX, DL
?????SHR?? EAX, 8
?????XOR?? EAX, [dwCRC32Table + EDX*4]
?????INC?? EBX
?????LOOP??_NextByte
?_Done:
?????NOT?? EAX
???}
?}