0 0 0

科锐学习笔记-第三阶段-Win32汇编 01 编译和链接

admin
212 0

本文共计17355个字,预计阅读时长69.4分钟。

目录

环境配置 

masm32下载 

​       官网:http://www.masm32.com/ 

安装 

 img 

成功标志 

img 

img 

环境配置: 

  •   -   将masm32下的bin目录添加到path     -   新建include,将masm32目录下的inclcude目录添加进去     -   新建lib,将masm32目录下的lib目录添加进去 

 img 

    测试代码 
.386 
.model flat, stdcall 
option casemap:none 

include windows.inc 
include user32.inc 

includelib user32.lib 

.data 
g_sz db "hello world", 0 
.code 
START: 
invoke MessageBoxA, NULL, offset g_sz, NULL, MB_OK 
end START 
``` 

编译链接后可以生成可执行文件就带配置成功 

![img](notesimg/1652959149901-ce78a4ef-eec2-4aca-aade-91247d3b260d.png) 

##### 编译链接: 

###### 1\. 编译 

​          ml /c /coff %1.asm(coff--PE) 

​         ml默认⽣成的⽂件格式是16位的,通过 /coff 32位程序的可执⾏⽂件格式来指定32位的格式 

###### 2\. 链接 

​       link /subsystem:windows %1.obj 

​       通过 /subsystem 来指定⼦系统, windows 是窗⼝程序, console 是控制台程序 

##### 编译脚本 build.bat: 

``` 
@echo off 
set include=D:\masm32\include 
set lib=D:\masm32\lib 
set path=D:\masm32\bin;D:\OllyICE_1.10 

del D:\OllyICE_1.10\udd\*.udd 

ml /c /coff %1.asm 
if errorlevel 1 goto err 

link /subsystem:windows %1.obj 
if errorlevel 1 goto err 

OllyICE.exe %1.exe 

:err 
``` 

或者 

``` 
ml /c /coff  %1.asm 

link /subsystem:windows %1..obj 

D:\OllyICE_1.10\OllyICE.exe %1.exe 

pause 
``` 

##### 代码在scode高亮 

![img](notesimg/1652959629494-589351a1-c2ff-462d-b070-58d2ac841e40.png) 

![img](notesimg/1652959691180-ce7dc7dd-74bb-4e35-af36-79c09851491a.png) 

### 16位与32位汇编的区别 

#### 1.源文件格式 

-   **文件头固定三件套:** 

-   ``` 
   .386     ; 表示使用的是386的是指令集 
   .model flat, stdcall ; 指明内存模型和调用约定 
   option casemap:NONE  ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE 
   ``` 

   -   **msdn宏汇编官网:**https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference?view=msvc-160 

   -   -   ![img](notesimg/1633605028106-77e38cc7-7786-416d-bfbc-6ecff3e057c3.png) 

   -   -   -   8086和286都是16位的,从386开始是32位,后缀+P的指可以使用跳转指令的(适用于面向内核)。 

   -   -   ![img](notesimg/1652959963277-7754f340-d954-4e74-b70e-03abe9d24ced.png) 
       -   casemap 最好只设 NONE   设all可能导致部分头文件没法用 
       -   ![img](notesimg/1652959985466-cfc06e90-5bad-4a01-bcc9-ff61a313b2ce.png) 

   -   **分段:**32位汇编取消 了分段,改用**内存属性**来划分,称作节(section)、内存区或内存块。 

   -   -   编写时每种类型可以定义多个,编译期会自动被同类归置 

   ![img](notesimg/1652960064694-fd7d56ad-d43b-483d-95f6-847cd6b1f6ea.png) 

``` 
.386     ; 表示使用的是386的是指令集,最低版本,也可以用更高版本,常用386 
.model flat, stdcall ; 指明内存模型和调用约定  只有c或者 stdcall 
option casemap:NONE  ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE 

.data 
   g_sz db "hello world", 0 
.data 
   g_sz0 db "hello world", 0 

.data? 
   g_sz dw ? 

.const 
   g_sz1 db "test test", 0 

.code 

START: 
end START 
``` 

#### 寄存器 

##### 寄存器长度 

![img](notesimg/1652960550871-63725a36-1afd-49a4-b5a2-ced90f264faa.png) 

32位 扩充了 8 个通用寄存器 和2个 ip 一次 flag 寄存器 ,  扩充成了32位,, 低16位仍然保留原来的名字, 高16位没有名字,要访问需要自己移位 , 段寄存器没有扩充且其功能发生了改变 

![img](notesimg/1652960572199-1a5f4847-e7a4-4c97-a447-11725acd5a70.png) 

##### 寄存器组 

![img](notesimg/1652960861210-6ce6d9fd-45db-46ec-a5de-9dcce0296e62.png) 

#### 调试 

32位汇编调试⼀般使⽤OD或者x64dbg,前者可以到看雪下载,后者可以到官⽹下载,两者建议都下 

载 

##### OD(OllICE)   

目前只能调试32位程序 

https://tool.pediy.com/      看雪官网 

![img](notesimg/1652961237809-af2ad943-9325-4df1-9695-d486dfe2750f.png) 

![img](notesimg/1652961267519-3586d1d9-d8c2-47b6-acee-4600c11dd790.png) 

解压密码:  pediy.com 

使用方式, 

1\.  把  exe 文件拖进去 
2\.  点击菜单 

![img](notesimg/1652961781846-454fd944-19aa-40c2-bd15-23a16502bee9.png)  

1\.  附近进程 :   调试正在运行的 
2\.  右键用  ollyice 打开 

![img](notesimg/1652961922828-5cdb699c-4d9c-471f-a944-2cf60a11db9c.png) 

![img](notesimg/1652964800072-ca8ba1ab-9111-4f66-86f4-ce4a843368a9.png) 

鼠标点击有时候高亮不准是因此你改动了代码,但是软件保存了上次的调试信息,删除即可 

删除上次调试保存的信息 

1\.  删除该文件里面的文件  

![img](notesimg/1652971605364-6757529c-3141-4a7c-a548-5887059a908d.png) 

1\.  通过OD去删,删除要先退出调试,删完在重新调试,否则内存里仍然还有数据 

![img](notesimg/1652971811112-b688992c-88f3-4d63-8fd0-31f130b2d81f.png) 

##### X32Debug 

可以调试64位程序 

官网: https://x64dbg.com/ 

x32dbg   调32位      x64dbg  调 64位 

##### 调试快捷键 

x32dbg 和 OD 的使用方式基本相同,包括快捷键 

![img](notesimg/1652960998678-313b7958-2c68-453d-b277-98f428e2c501.png) 

**F4:运行到光标处。** 

**esp: 回到栈顶** 

**+/-   查看 下一步/上一步  运行的代码** 

**菜单  查看断点可以查看所有的断点** 

#### 指令补充 

串操作现在支持一次四个字节的操作(26位只支持最高2字节) 

-   8086所有指令在32位保持原有功能不变,操作数长度扩充到32位。 

![img](notesimg/1652964991952-0b5399c6-3f85-4495-998a-bed8ebcfb3d8.png) 

movsx:高位补0,低位补1。 

movzx:全部补0。 

#### 寻址 

-   相对于16位汇编,32位寻址的变化: 

-   -   1.在基址寻址和基址变址寻址两种寻址操作上面更加宽松: 

-   -   -   基址寄存器:通用寄存器都可用作基址寄存器; 
       -   变址寄存器:除ESP外都可以用作变址寄存器。 
       -   *当基址为EBP或ESP时,访问的是栈上的数据。 

-   -   2.同时增加了比例因子寻址:变址寄存器 × 比例因子(1、2、4、8),便于遍历不同长度的数组。 

![img](notesimg/1652965228487-cc457d5f-e9b6-48da-af3b-33b5adafa441.png) 

``` 
.386 
.model flat, stdcall 
option casemap:NONE 

include windows.inc 
include user32.inc 
includelib user32.lib 
.data 
   g_szTitle db "hello world", 0  
.data 
   g_sz db "hello world", 0  
   g_sz0 db "hello world", 0  
   g_ary dw 1111h,2222h,3333h,4444h,5555h 
.data? 
   g_dw dw ? 
.const 
   g_sz1 db "test test",0 
.code 

START: 
   mov eax,offset g_ary 
   xor ecx,ecx 
   mov bx,[eax+ecx*type g_ary] 
   inc ecx 
   mov bx,[eax+ecx*type g_ary] 
   inc ecx 
   mov bx,[eax+ecx*type g_ary] 
   inc ecx 
   mov bx,[eax+ecx*type g_ary] 

   mov eax,offset g_sz 
   mov ebx,offset g_sz0 
   mov edx,offset g_sz1 
   mov ecx,offset g_dw 
   mov byte ptr [eax],'a' 

   mov esi,1 
   mov byte ptr [eax+esi],'b' 

   mov edx,offset g_sz1 
   mov byte ptr [edx+esi+1],'c' 

   ;invoke MessageBoxA, NULL, offset g_szTitle, NULL, MB_OK 
end START 
``` 

### 调用API,弹MessageBox代码示例 

``` 
.386                  ; 表示使用的是386的是指令集 
.model flat, stdcall  ; 指明内存模型和调用约定 
option casemap:NONE   ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE 

include windows.inc  
include user32.inc  
include kernel32.inc  

includelib user32.lib  
includelib kernel32.lib  

.data 
   g_szText db "hello world", 0 
   g_szTitle db "cr42 asm32", 0 

.code 
START: 
   invoke MessageBoxA, NULL, offset g_szText, offset g_szTitle, MB_OK 
   invoke ExitProcess, 0 
end START 
``` 

### 汇编版的第一个窗口 

SDK 版弹窗 

``` 
#include <windows.h> 

void ShowErrMsg(); 

LRESULT CALLBACK CR42WindowProc(HWND hwnd,      // handle to window 
 UINT uMsg,      // message identifier 
 WPARAM wParam,  // first message parameter 
 LPARAM lParam   // second message parameter 
) 
{ 
 switch (uMsg) 
 { 
 case WM_LBUTTONDOWN: 
 { 
   WORD wX = LOWORD(lParam); 
   WORD xY = HIWORD(lParam); 

   char szBuf[MAXBYTE] = {0}; 
   wsprintf(szBuf, "x:%d y:%d", wX, xY); 
   MessageBox(hwnd, szBuf, NULL, MB_OK); 

   return 0; 
 } 
 case WM_CLOSE: 
 { 
   int nRet = MessageBox(hwnd, "亲,是否要关闭窗口!", NULL, MB_OKCANCEL); 
   if (nRet == IDOK) 
   { 
     DestroyWindow(hwnd);//销毁窗口 
   } 
   return 0; 
 } 
 case WM_DESTROY://窗口已经被销毁 
   PostQuitMessage(0); 
   return 0; 
 } 

 return DefWindowProc(hwnd, uMsg, wParam, lParam); //自己不想处理的消息,交给系统默认处理即可 
} 

int WINAPI WinMain(HINSTANCE hInstance,      // handle to current instance 
 HINSTANCE hPrevInstance,  // handle to previous instance 
 LPSTR lpCmdLine,          // command line 
 int nCmdShow              // show state 
) 
{ 
 WNDCLASS wc; 
 wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格 
 wc.lpfnWndProc = CR42WindowProc;//函数 
 wc.cbClsExtra = 0;//窗口类对象额外内存大小,一般不用 
 wc.cbWndExtra = 0;//窗口实例对象额外内存大小,一般不用 
 wc.hInstance = hInstance;//实例句柄 
 wc.hIcon = NULL;//没有图标 
 wc.hCursor = NULL;//没有光标 
 wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);//背景颜色 
 wc.lpszMenuName = NULL;//没有菜单 
 wc.lpszClassName = "cr42 class";//窗口类的类名 
 ATOM nRet = RegisterClass(&wc); 
 if (nRet == 0) 
 { 
   MessageBox(NULL, "注册窗口类失败!", NULL, MB_OK); 
   return 0; 
 } 
 //wc.lpszClassName = "cr42 class2";//窗口类的类名 
 //nRet = RegisterClass(&wc); 
 //if (nRet == 0) 
 //{ 
 //  ShowErrMsg(); 
 //} 
 //DWORD dwErr = GetLastError(); 

 //创建窗口实例 
 HWND hWnd = CreateWindow("cr42 class", //窗口类类名 
   "我的第一个窗口", 
   WS_OVERLAPPEDWINDOW,//重叠窗口 
   CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,//坐标和尺寸大小 
   NULL,//父窗口,没有 
   NULL,//菜单,没有 
   hInstance, 
   NULL);//参数,暂时不用 
 if (hWnd == NULL) 
 { 
   ShowErrMsg(); 
   return 0; 
 } 

 //3 显示窗口 
 ShowWindow(hWnd, SW_SHOW);//正常显示窗口 

 //4\. 更新窗口 
 UpdateWindow(hWnd); 

 // WM_MOUSEMOVE 
 //WM_KEYDOWN 

 //消息循环 
 MSG msg; 
 while (GetMessage(&msg, NULL, 0, 0)) 
 { 
   //CR42WindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); 
   DispatchMessage(&msg); 
 } 

#if 0 
 DWORD dw = CS_HREDRAW | CS_VREDRAW; //多种风格组合 
 if (dw & CS_HREDRAW)//判断风格 
 { 
 } 
 dw = dw & (~CS_HREDRAW); //取消风格 

#endif // 位运算在SDK中广泛应用 
 return 0; 
} 

void ShowErrMsg() 
{ 
 LPVOID lpMsgBuf; 
 FormatMessage( 
   FORMAT_MESSAGE_ALLOCATE_BUFFER | 
   FORMAT_MESSAGE_FROM_SYSTEM | 
   FORMAT_MESSAGE_IGNORE_INSERTS, 
   NULL, 
   GetLastError(), 
   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 
   (LPTSTR)&lpMsgBuf, 
   0, 
   NULL 
 ); 
 // Process any inserts in lpMsgBuf. 
 // ... 
 // Display the string. 
 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION); 
 // Free the buffer. 
 LocalFree(lpMsgBuf); 
} 

``` 

ASM32 版 

查找变量定义 或者  函数的文件或库 

![img](notesimg/1652966810371-d5eae963-ee57-4a31-9d3c-58392ff665c2.png) 

``` 
.386                  ; 表示使用的是386的是指令集 
.model flat, stdcall  ; 指明内存模型和调用约定 
option casemap:NONE   ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE 

include windows.inc  
include user32.inc  
include kernel32.inc  

includelib user32.lib  
includelib kernel32.lib  

.data 
   g_szClassName db "cr42asm32Class", 0 
   g_szTitle db "这个是我的第一个汇编窗口", 0 
.code 

; 过程函数 
WindowProc PROC stdcall hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 

    .IF uMsg == WM_CLOSE 
       invoke PostQuitMessage, 0    ;退出 
   .ENDIF 

   invoke DefWindowProc, hWnd, uMsg, wParam, lParam 
   ret 
WindowProc ENDP 

;函数入口     
WinMain Proc hInstance:HINSTANCE 
   local @wc:WNDCLASS     ;窗口类 
   local @hWnd:HWND       ;窗口句柄 
   local @msg:MSG         ;消息队列 

   ;sdk注册窗口类 
   ;WNDCLASS wc; 
   ;wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格 
   ;wc.lpfnWndProc = CR42WindowProc;   //函数 
   ;wc.cbClsExtra = 0;      //窗口类对象额外内存大小,一般不用 
   ;wc.cbWndExtra = 0;    //窗口实例对象额外内存大小,一般不用 
   ;wc.hInstance = hInstance;  //实例句柄 
   ;wc.hIcon = NULL;    //没有图标 
   ;wc.hCursor = NULL;   //没有光标 
   ;wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);//背景颜色 
   ;wc.lpszMenuName = NULL;//没有菜单 
   ;wc.lpszClassName = "cr42 class";//窗口类的类名 
   ;ATOM nRet = RegisterClass(&wc); 
   ;if (nRet == 0) 
   ;{ 
     ; return 0; 
   ;} 

   ; 注册窗口类 
   mov @wc.style, CS_VREDRAW or CS_HREDRAW 
   mov @wc.lpfnWndProc, offset WindowProc 
   mov @wc.cbClsExtra,0  
   mov @wc.cbWndExtra, 0 
   push hInstance 
   pop @wc.hInstance 
   ;设置图标 

   invoke LoadIcon,NULL,IDI_APPLICATION 
   mov @wc.hIcon,eax 

   ;设置光标 
   invoke LoadCursor,NULL,IDC_ARROW    
   mov @wc.hCursor,eax 

   mov @wc.hbrBackground, COLOR_WINDOW+1 
   mov @wc.lpszMenuName,NULL 
   mov @wc.lpszClassName, offset g_szClassName  
   invoke RegisterClassA, addr @wc 
   .IF eax == 0 
       ret 
   .ENDIF 

   ; HWND hWnd = CreateWindow("cr42 class", //窗口类类名 
   ; "我的第一个窗口", 
   ; WS_OVERLAPPEDWINDOW,//重叠窗口 
   ; CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,//坐标和尺寸大小 
   ; NULL,//父窗口,没有 
   ; NULL,//菜单,没有 
   ; hInstance, 
   ; NULL);//参数,暂时不用 
   ;if (hWnd == NULL) 
   ;{ 
   ;  return 0; 
   ;} 

   ; 创建窗口示例   返回值  eax 窗口句柄 
   invoke CreateWindowExA,  
       0,  
       offset g_szClassName,  
       offset g_szTitle,  
       WS_OVERLAPPEDWINDOW or WS_VISIBLE, 
       CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, 
       NULL, NULL, hInstance, NULL 
   .IF eax == NULL 
       ret 
   .ENDIF  
   mov  @hWnd,eax 

   ;ShowWindow(hWnd, SW_SHOW);   ;显示窗口 
   ;UpdateWindow(hWnd);          ;更新窗口 

   ;显示窗口 
   invoke ShowWindow, @hWnd,SW_SHOW 
   ;更新窗口 
   invoke UpdateWindow,@hWnd 

    ;MSG msg; 
    ;while (GetMessage(&msg, NULL, 0, 0)) 
    ;{ 
    ;  TranslateMessage(&msg); 
    ;  DispatchMessage(&msg); 
    ;} 

   ; 消息循环 
   .WHILE TRUE 
       invoke GetMessage, addr @msg, NULL, 0, 0 
       .IF eax == 0 
          .break 
       .ENDIF  
       invoke TranslateMessage, addr @msg 
       invoke DispatchMessage, addr @msg 
   .ENDW 

   ret  
WinMain endp 

START: 
   invoke GetModuleHandleA, NULL  ;获取实例句柄 
   invoke WinMain, eax            ;调用入口函数 

   invoke ExitProcess, 0          ;退出程序 
end START 
``` 

### 作业 

在窗口中间实时显示当前时间 

``` 
 g_szFormat db ' 当前时间:%d-%02d-%02d %02d:%02d:%02d ',0 

.code 

; 过程函数 
WindowProc PROC stdcall hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
   local @ps:PAINTSTRUCT      
   local @hDc:HDC        
   local @rcClient:RECT         
   local @sys:SYSTEMTIME 

   .IF uMsg == WM_CLOSE 
       invoke PostQuitMessage, 0    ;退出 

   .ELSEIF  uMsg == WM_TIMER 

       invoke  InvalidateRect,hWnd,NULL,TRUE 
       invoke  UpdateWindow,hWnd 

   .ELSEIF  uMsg == WM_PAINT 
       invoke  BeginPaint,hWnd,addr @ps 
       mov @hDc,eax 
       invoke  GetClientRect,hWnd,addr @rcClient 

       ;获取系统当前时间 
       invoke  GetLocalTime,addr @sys 
       ;格式化时间,倒着来的 先秒,后分钟...最后年 
       ;SYSTEMTIME 的成员是 wrod,要转成 dword 在传参 
       movzx eax,@sys.wSecond     ;将 @sys.wSecond 的值拓展成dword   
       push eax                  ;将 @sys.wSecond 的值入栈 
       movzx eax,@sys.wMinute 
       push eax 
       movzx eax,@sys.wHour 
       push eax 
       movzx eax,@sys.wDay 
       push eax 
       movzx eax,@sys.wMonth 
       push eax 
       movzx eax,@sys.wYear 
       push eax 
       push offset g_szFormat 
       push offset g_szBuffer 
       invoke  wsprintf 

       ;invoke  wsprintf,offset g_szTime,offset g_szFormat,@sys.wYear,@sys.wMonth,@sys.wDay,@sys.wHour,@sys.wMinute,@sys.wSecond 
       ;画图 
       invoke  DrawText, @hDc,offset g_szBuffer,30,addr @rcClient,DT_CENTER or DT_VCENTER or DT_SINGLELINE 
       invoke  EndPaint,hWnd,addr @ps 
   .ENDIF    

  ;case WM_TIMER: 
  ;{ 
  ;    InvalidateRect(hwnd, NULL, TRUE); 
  ;    UpdateWindow(hwnd);//有无效区调用过程函数,没有无效区,什么事都不做 
  ;} 
  ;case WM_PAINT: 
  ;{ 
  ;    PAINTSTRUCT ps; 
  ;    HDC hDc = BeginPaint(hwnd, &ps);//获取窗口的DC 

  ;    RECT rcClient; 
  ;    GetClientRect(hwnd, &rcClient); //获取客户区矩形 

  ;    char szBuff[100] = ""; 
  ;    SYSTEMTIME sys; 
  ;    GetLocalTime(&sys); 
  ;    wsprintf(szBuff,"%4d-%02d-%02d %02d:%02d:%02d", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond);      
  ;    DrawText(hDc, szBuff, strlen(szBuff), &rcClient,DT_CENTER|DT_VCENTER|DT_SINGLELINE); 
  ;    EndPaint(hwnd, &ps);//释放BeginPaint申请的资源 
  ;} 

   invoke DefWindowProc, hWnd, uMsg, wParam, lParam 
   ret 
WindowProc ENDP 

;函数入口     
WinMain Proc hInstance:HINSTANCE 
   local @wc:WNDCLASS     ;窗口类 
   local @hWnd:HWND       ;窗口句柄 
   local @msg:MSG         ;消息队列 

   ;sdk注册窗口类 
   ;WNDCLASS wc; 
   ;wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格 
   ;wc.lpfnWndProc = CR42WindowProc;   //函数 
   ;wc.cbClsExtra = 0;      //窗口类对象额外内存大小,一般不用 
   ;wc.cbWndExtra = 0;    //窗口实例对象额外内存大小,一般不用 
   ;wc.hInstance = hInstance;  //实例句柄 
   ;wc.hIcon = NULL;    //没有图标 
   ;wc.hCursor = NULL;   //没有光标 
   ;wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);//背景颜色 
   ;wc.lpszMenuName = NULL;//没有菜单 
   ;wc.lpszClassName = "cr42 class";//窗口类的类名 
   ;ATOM nRet = RegisterClass(&wc); 
   ;if (nRet == 0) 
   ;{ 
     ; return 0; 
   ;} 

   ; 注册窗口类 
   mov @wc.style, CS_VREDRAW or CS_HREDRAW 
   mov @wc.lpfnWndProc, offset WindowProc 
   mov @wc.cbClsExtra,0  
   mov @wc.cbWndExtra, 0 
   push hInstance 
   pop @wc.hInstance 
   ;设置图标 

   invoke LoadIcon,NULL,IDI_APPLICATION 
   mov @wc.hIcon,eax 

   ;设置光标 
   invoke LoadCursor,NULL,IDC_ARROW    
   mov @wc.hCursor,eax 

   mov @wc.hbrBackground, COLOR_WINDOW+1 
   mov @wc.lpszMenuName,NULL 
   mov @wc.lpszClassName, offset g_szClassName  
   invoke RegisterClassA, addr @wc 
   .IF eax == 0 
       ret 
   .ENDIF 

   ;sdk 窗口实例化 
   ; HWND hWnd = CreateWindow("cr42 class", //窗口类类名 
   ; "我的第一个窗口", 
   ; WS_OVERLAPPEDWINDOW,//重叠窗口 
   ; CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,//坐标和尺寸大小 
   ; NULL,//父窗口,没有 
   ; NULL,//菜单,没有 
   ; hInstance, 
   ; NULL);//参数,暂时不用 
   ;if (hWnd == NULL) 
   ;{ 
   ;  return 0; 
   ;} 

   ; 创建窗口示例   返回值  eax 窗口句柄 
   invoke CreateWindowExA,  
       0,  
       offset g_szClassName,  
       offset g_szTitle,  
       WS_OVERLAPPEDWINDOW or WS_VISIBLE, 
       CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, 
       NULL, NULL, hInstance, NULL 
   .IF eax == NULL 
       ret 
   .ENDIF  
   mov  @hWnd,eax 

   ;sdk更新显示窗口 
   ;ShowWindow(hWnd, SW_SHOW);   ;显示窗口 
   ;UpdateWindow(hWnd);          ;更新窗口 

   ;显示窗口 
   invoke ShowWindow, @hWnd,SW_SHOW 
   ;更新窗口 
   invoke UpdateWindow,@hWnd 

   ;SetTimer(hWnd, 0x9527, 500, NULL); //开启定时器 

   ;开启定时器 
   invoke SetTimer,@hWnd, 0027H, 100, NULL 

   ;MSG msg; 
   ;while (GetMessage(&msg, NULL, 0, 0)) 
   ;{ 
   ;  TranslateMessage(&msg); 
   ;  DispatchMessage(&msg); 
   ;} 

   ; 消息循环 
   .WHILE TRUE 
       invoke GetMessage, addr @msg, NULL, 0, 0 
       .IF eax == 0 
          .break 
       .ENDIF  
       invoke TranslateMessage, addr @msg 
       invoke DispatchMessage, addr @msg 
   .ENDW 

   ret  
WinMain endp 

START: 
   invoke GetModuleHandleA, NULL  ;获取实例句柄 
   invoke WinMain, eax            ;调用入口函数 

   invoke ExitProcess, 0          ;退出程序 
end START 

最新回复 ( 0 )
全部楼主