当前位置: 首页 > article >正文

RadASM环境,win32汇编入门教程之六

;运行效果

;RadASM环境,win32汇编入门教程之六
;在上一个教程里面,我们学习了如何定义数据,那么在这一章节里面,我们来学习一下,再说明怎么把这些数据显示出来
;下列就是显示出这些数据的示例程序,可以直接复制下来,然后编译运行看看效果
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386 
.model flat,stdcall 
option casemap:none 
include      windows.inc 
include      user32.inc 
include      kernel32.inc 
include      gdi32.inc         ;增加的内容

includelib   user32.lib        
includelib   kernel32.lib 
includelib   gdi32.lib         ;增加的内容
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD       
                                                
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.DATA                                   
ClassName           db "SimpleWinClass",0        
AppName             db "窗口程序的模版",0
   
sF db "%d",0
     
hA dd 168 
hD db "世界,你好!",0  
.DATA?                                  
hInstance   HINSTANCE  ?                
CommandLine LPSTR      ?
hB          dd ?
.const;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
hC          equ 16800                                         
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.CODE                      

start:                      
invoke GetModuleHandle, NULL                                                    
mov hInstance,eax 
invoke GetCommandLine                                                                                       
mov CommandLine,eax 
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT        
invoke ExitProcess, eax                                          
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD 
        LOCAL wc:WNDCLASSEX                                          
        LOCAL msg:MSG 
        LOCAL hwnd:HWND 
        
        mov   wc.cbSize,SIZEOF WNDCLASSEX                            
        mov   wc.style, CS_HREDRAW or CS_VREDRAW                     
        mov   wc.lpfnWndProc, OFFSET WndProc                        
        mov   wc.cbClsExtra,NULL 
        mov   wc.cbWndExtra,NULL 
        push  hInstance 
        pop   wc.hInstance 
        mov   wc.hbrBackground,COLOR_WINDOW 
        mov   wc.lpszMenuName,NULL 
        mov   wc.lpszClassName,OFFSET ClassName 
        invoke LoadIcon,NULL,IDI_APPLICATION                          
        mov   wc.hIcon,eax 
        mov   wc.hIconSm,eax 
        invoke LoadCursor,NULL,IDC_ARROW                              
        mov   wc.hCursor,eax 
        invoke RegisterClassEx, addr wc                              
        invoke CreateWindowEx,NULL, ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,100,100,400,300, NULL,NULL,hInst, NULL 
        mov   hwnd,eax 
        invoke ShowWindow, hwnd,CmdShow                              
         invoke UpdateWindow, hwnd                                    

        .while TRUE                                                   
                invoke GetMessage, ADDR msg,NULL,0,0 
                .break .if (!eax) 
                invoke TranslateMessage, ADDR msg 
                invoke DispatchMessage, ADDR msg 
        .endw 
        mov     eax,msg.wParam                                         
        ret 
WinMain endp 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
         LOCAL @stPs:PAINTSTRUCT
         LOCAL @szBuffer[256]:byte 
         LOCAL @hDc
        
         .if uMsg == WM_CREATE                

        .elseif uMsg == WM_PAINT       
                invoke BeginPaint,hWnd,addr @stPs
                mov    @hDc,eax 
                ;下面显示168
                invoke wsprintf,addr @szBuffer,addr sF,hA           
                invoke lstrlen,addr @szBuffer
                invoke TextOut,@hDc,100,30,addr @szBuffer,eax       ;显示函数
                ;下面显示1680
                mov hB,1680
                invoke wsprintf,addr @szBuffer,addr sF,hB
                invoke lstrlen,addr @szBuffer
                invoke TextOut,@hDc,100,60,addr @szBuffer,eax
                ;下面显示16800
                invoke wsprintf,addr @szBuffer,addr sF,hC
                invoke lstrlen,addr @szBuffer
                invoke TextOut,@hDc,100,90,addr @szBuffer,eax
                ;下面显示"世界,你好!"
                invoke lstrlen,addr hD
                invoke TextOut,@hDc,100,120,addr hD,eax
                
                invoke EndPaint,hWnd,addr @stPs  
        .elseif uMsg == WM_DESTROY                                           
                invoke PostQuitMessage,NULL                               
        .else 
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam             
        ret 
    .endif 
    xor eax,eax 
    ret 
WndProc endp 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start   

;在这个示例里面,我们显示4个东西,分别是数字168、1680、16800和字符串"世界,你好!"
;首先,需要增加1个头文件和库文件,就是上面添加的
include      gdi32.inc
includelib   gdi32.lib
;这些文件里面定义了一些基本的数据结构之类的,就是微软公司先把一些最基础的定义好了,后面就可以直接调用一些函数。
;经常编译不过的时候,提示没有定义某个函数之类的,往往就是缺少了这些头文件。gdi32文件是关于一些绘画的函数。

;先看这句: hA dd 168 ,这就是定义一个叫hA的4字节数字168,hA是名称,dd是dword的简称,即4字节,就是32位的意思,因为每个字节是8位
;可不可以定义成hA db 168 呢,也可以,这样定义的话就是定义1个单字节的值。但很少这样做,因为后面调用的函数参数基本是32位的,如果定义成1个字节的话
;后面要转成32位的值,还要保证高位字节都是零,才能当做参数调用函数,所以默认的都是定义成dd类型。
;上面有个单词 .DATA,这个指的是数据区,设定初值的数据放在这个区里面。

;看第2个定义:  hB dd ?
;它放在 .DATA? 这里,这是未初始化的数据区,就是先定义,不赋值先。

;看第3个定义:  hC equ 16800 
;它放在 .const ,这个是固定数据区,就是放在这儿的是不能改变的数据。这里用了一个命令equ,它是等同的意思。就是说hC就是16800,但不能说16800就是hC,因为在程序中或程序运行中,可能也会产生16800的值。

;看第4个定义: hD db "世界,你好!",0 
;它放在 .DATA,即放在数据区,是设定了初值的,在程序中也可以改变
;它是定义1个字符串,db是dword byte的缩写,就是4字节作为地址值。我们需要这样理解,hD并不等于这个字符串,而是这个字符串的地址,也叫指针值。

;后面研究一下,在窗口函数WndProc中有哪些内容
;先定义1个名叫@stPs的PAINTSTRUCT结构变量,这个名字@stPs随便取的,一般约定成俗的局部变量前面加@而已。
;那什么叫局部变量,局部变量就是在函数运行期内,它是有效的,离开函数时就被电脑收回了。
;那什么时候离开?当程序运行时,走到最后一个命令ret,就是返回上一层,即调用它的那一层,就是离开了这个函数了。
;像@stPs这个变量,它定义在WndProc函数内,当WndProc函数运行完,返回上一层后,它就不能再被其它的函数调用了,不能再使用了。

;PAINTSTRUCT这个结构是什么东西,看它的字面意思就知道,它是画的结构
;简单地说,就是重新画这个窗口时,根据这个结构内的设定值重新画它。
;为什么要重画它?
;很多情况要重画,比如里面要显示的内容发生变化,或最小化状态恢复原状,或被其它窗口挡住又恢复了等等。
;具体的我们以后再研究,这里可以先定义,当然,只是定义,结构内的成员还没有实际值的。

;@szBuffer是准备中转用的字符串数组的变量。因为前面定义的像hA,hB,hC是数值,不是字符串,后面在显示前要转化为字符串才行。
;我们要知道,数值是不能直接显示出来的,就算你看到窗口上写着123之类的这些东西,它并不是数值,而是字符串。
;就像你拍了一张文档,看起来是文字,但其实它是相片。

;@hDc是为后面储值用的变量,也可以这样写 @hDc:dword,只是后面的dword省略了,后面没有像:dword这样或类似的类型说明的,都是默认为dword型,即4字节型。

;看.elseif uMsg == WM_PAINT 这句,这句的意思是,当要重绘时,要干什么
;就是说,当重绘消息来时,要怎么画这个窗口
;比如电脑刚把程序运行起来,需要重绘
;比如最小化之后又恢复原状,怎么重新画出来,需要重绘等等
;电脑要怎么重绘时,就在WM_PAINT下面找这些代码


;invoke BeginPaint,hWnd,addr @stPs 这句的意思是,得到窗口原来的设定,并把它保存到@stPs里面去。
;就是把窗口有多长,有多宽,要不要在重绘之前,把原来没被挡住的部分保存原样,或者要不要原来显示的擦除掉等等。
;这些具体的我们不用管它,让电脑自已处理。我们要做的就是把我们需要增加上去的内容,告诉电脑,一起画出来。
;这些内容,就是我们想显示的4个东西了。

;mov    @hDc,eax 就是把得到的设定保存起来,可以理解为把这个程序窗口保存下来。后面要显示什么的,告诉电脑,把要显示的东西显示到这个程序窗口上去,而不是其它的程序窗口。

;invoke wsprintf,addr @szBuffer,addr sF,hA 这句的意思是,因为hA是个数字,不能直接显示,要先通过格式化函数wsprintf把hA转化为字符串,并保存到@szBuffer里面去。
;invoke lstrlen,addr @szBuffer 这句的意思是,得到@szBuffer这个字符串的长度,后面紧跟着的eax就是这个函数的返回值,即字符串的长度
;invoke TextOut,@hDc,100,30,addr @szBuffer,eax 这句的意思是在坐标为100.30的地方把字符串@szBuffer显示出来,坐标从左上角开始算。

;显示1680时,因为前面是未初始化的,就是没有给定值的,所以这里要赋值给它。mov hB,1680
;显示16800时,前面也相当于初始化了,所以同样操作进行显示。
;而显示"世界,你好!"时,因为它是已经初始化了的,且定义的是字符串,所以可以直接使用函数TextOut把它显示在窗口上。

;invoke EndPaint,hWnd,addr @stPs  这一句的意思是,在指定窗口中标记绘制的结束
;BeginPaint与EndPaint是配对出现在,在它们的之间是重绘的内容。

;以上是显示数字或字符串的示例,当然,仅仅是显示了内容。
;看起来还是不太好看,还有一些东西可以改变,比如字体、字体大小、前景色或文本色等。这些我们在下一个教程里再学习。


http://www.kler.cn/a/552757.html

相关文章:

  • MySQL 索引失效处理:原因分析与优化实战
  • vue3项目,旅游景点页面
  • 高电服务器托管:企业IT基础设施的可靠之选
  • MySQL + Python 开发之旅:初识数据库与连接搭建
  • Docker 私有仓库 Harbor 详解
  • Flask的知识点总结
  • VScode运行C语言提示“#Include错误,无法打开源文件stdio.h”
  • Vue中事件名的命名规范
  • 打开多个chrome历史记录
  • IDEA中集成Maven
  • 一问读懂AI工具—DeepSeek、Kimi、豆包、文心一言、通义千问
  • 【C++】结构体排序+sort(),cmp()参数写法口诀
  • 社群共建与共享:以十点读书会为例探讨开源AI智能名片2+1链动模式S2B2C商城小程序的应用
  • 从C语言源码到可执行文件的生成过程通常包括
  • List<Map<String, Object>> 如何对某个字段求和
  • 25/2/18 <算法笔记> ByteTrack
  • 阿里云前端自动化部署流程指南
  • 《DeepSeek赋能工业互联网:解锁数据深度分析新姿势》
  • 【Elasticsearch】分页查询
  • Pycharm打开的jupyter notebook无法在pycharm中关闭怎么解决