hacker0058 发表于 2006-6-19 19:17:25

汇编写的一个最简单的窗口程序

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;               Programmed by hacker0058, [email protected]
;                         Website: http://hacker0058.ys168.com
;                                   汇编(MASM):最简单的窗口
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


;==============================编译参数(必须的)=======================

.386;汇编语言伪指令,他告诉编译器我们的程序是使用80386指令集编写的,还有486,586等
.model flat,stdcall;告诉编译器内存模型是FLAT,参数的传递约定是stdcall(从右到左,恢复堆栈的工作交由被调用者)
option casemap:none   ;告诉MASM编译器:要区分标号的大小写

;================================头文件============================

include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib   
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

;==================================子程序声明=======================

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD   ;调用子程序前先定义参数

;===================================已初始化的数据===================

.DATA         ; 可以看成易语言里的常量,要占用程序空间
ClassName db "SimpleWinClass",0      ; 窗口类名
AppName db "Our First Window",0      ; 窗口标题

;==================================未初始化的数据====================

.DATA?                ; 相当于易语言里的全局变量,后面要带?号,不占用程序空间
hInstance HINSTANCE ?      ;
CommandLine LPSTR ?

;=====================================程序代码段====================

.CODE                ; 程序代码开始标识
start:            ;标签
invoke GetModuleHandle, NULL            ; 取程序模块句柄
                              
mov hInstance,eax   ; 赋值到全局变量
invoke GetCommandLine   ; 取程序命令行
                                                                     
mov CommandLine,eax   ; 赋值到全局变量
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT      ; 调用子程序
invoke ExitProcess, eax                           ; 退出程序,必须的


;============================模板结束==============================


;---------------------------------子程序WinMain -------------------------------

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX    ;局部变量                                       
    LOCAL msg:MSG          ;同上
    LOCAL hwnd:HWND      ;同上

    mov   wc.cbSize,SIZEOF WNDCLASSEX                   ; 赋值:WNDCLASSEX的大小
    mov   wc.style, CS_HREDRAW or CS_VREDRAW         ;赋值:窗口具有的风格
    mov   wc.lpfnWndProc, OFFSET WndProc          ;赋值:窗口处理函数的指针
    mov   wc.cbClsExtra,NULL                        ;赋值:指定紧跟在窗口类结构后的附加字节数。
    mov   wc.cbWndExtra,NULL                ;赋值:指定紧跟在窗口事例后的附加字节数
    pushhInstance    ;压饯
    pop   wc.hInstance;出饯,赋值本模块的实例句柄
    mov   wc.hbrBackground,COLOR_WINDOW+1;背景画刷的句柄
    mov   wc.lpszMenuName,NULL    ;指向菜单的指针,这里没有
    mov   wc.lpszClassName,OFFSET ClassName;窗口类名
    invoke LoadIcon,NULL,IDI_APPLICATION   ;API载入一个图标
    mov   wc.hIcon,eax                     ;赋值:图标的句柄
    mov   wc.hIconSm,eax                  ;赋值:关联的小图标
    invoke LoadCursor,NULL,IDC_ARROW      ;API载入一个鼠标指针
    mov   wc.hCursor,eax      ;赋值鼠标指针
    invoke RegisterClassEx, addr wc   ;注册窗口类后,再调用CreateWindowEx产生实际的窗口
    invoke CreateWindowEx ,NULL,\
               ADDR ClassName,\                                       
                ADDR AppName,\                                 
                WS_OVERLAPPEDWINDOW,\                        
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                NULL,\         
                NULL,\         
                hInst,\      
                NULL            
    mov   hwnd,eax   ;保存新建窗口的句柄
    invoke ShowWindow, hwnd,CmdShow               ; 调用ShowWindow显示这个窗口
    invoke UpdateWindow, hwnd                     ; 调用 UpdateWindow 来更新客户区

    .WHILE TRUE                                    ; 判断循环首 (真)
                invoke GetMessage, ADDR msg,NULL,0,0 ;接收消息,如果接收到WM_QUIT消息后会返回零
                .BREAK .IF (!eax)       ;如果真(eax=0),跳出循环()
   ;下面2行等同于易里面的处理事件()            
                invoke TranslateMessage, ADDR msg;处理按键消息
                invoke DispatchMessage, ADDR msg   ;发送给负责该窗口过程的函数
   .ENDW                                          ;判断循环尾 ()
    mov   eax,msg.wParam         ; 程序退出码,Windows 规范
    ret                              
WinMain endp                        ;程序段结束

;--------------------------------窗口回调函数-----------------------------------

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM    ;窗口回调函数
    .IF uMsg==WM_DESTROY                        ;判断接收的消息是否是WM_DESTROY消息(程序结束后由Windows传递过来)
      invoke PostQuitMessage,NULL             ; 如果是就发一条WM_QUIT消息给自己,使得GetMessage结束消息循环
    .ELSE                                       ;否则
      invoke DefWindowProc,hWnd,uMsg,wParam,lParam   ; 就把接收到的参数传递给Windows缺省的窗口处理函数
      ret    ;返回
    .ENDIF                              ;判断结束
    xor eax,eax;处理消息后eax要清零,让消息不再向下传递,即让窗口回调函数返回 (假)
   ret         
WndProc endp      ;程序段结束

end start   ;标签结束(代码结束)

hacker0058 发表于 2006-6-19 19:28:32

这个程序编译出来只有3K

运行后会出现一个空白窗口,可以最小化,最大化,关闭等窗口基本操作

如果用易写个这样的空白窗口程序,非独立编译都有6.8K

要是带上支持库,要有535 K

天啊,易没法用了

不过,用汇编写多窗口的程序那可能要累死人的

总结:汇编最好用来写小程序(无窗口程序)

微微虫 发表于 2006-6-19 20:40:03

好,顶一下
写Windows窗口程序基本差不多

caterpilla 发表于 2006-6-19 20:56:17

汇编确实是累。。。。。。。
感觉高级语言结合汇编更合理些,毕竟很多东西通用的,不必用这么底层的东西。

sam2006cn 发表于 2006-6-27 21:38:18

真的很难.

~逍遥~ 发表于 2006-7-2 03:25:01

嗯4 楼的说的有道理!

飘云 发表于 2006-7-2 09:55:42

原帖由 hacker0058 于 2006-6-19 19:17 发表
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ...


这是Iczelion写的吧?

kntpenguin 发表于 2006-7-2 14:39:40

不懂,装懂也不懂,我就不装了!

m0rri 发表于 2006-7-11 04:54:02

是Iczelion写的吧?


----- 那个手册放出来下撒。。~~?

hacker0058 发表于 2006-7-11 18:36:28

是的,我翻译了下
页: [1] 2
查看完整版本: 汇编写的一个最简单的窗口程序