;运行效果
;win32汇编环境,函数的编写与调用、传值或返回值等
;函数在被调用的时候,如果此函数实体在前面,可以不用声明。如果实体在后面,则需要先声明。类似于下面的DlgProc函数,因为它的实体在后面,所以需要在调用之前声明。
;看这一段 DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数
;DlgProc是函数名称,proto是说明此函数是私有的,就是本程序可以调用。反之则是public,即是公共类型的,可以让其它外面的程序调用,这个一般写在dll文件里面。
;:DWORD则说明这个参数的类型,即为四字节,32位的值。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
; 自定义函数声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数声明
AProc proto ;无参数函数声明
BProc proto :DWORD,:DWORD ;有参数函数声明
CProc proto :DWORD ;有参数函数,且参数为指针的声明,看起来体现不出指针的意思,和上面差不多。在汇编的眼中,其实没有什么指针的概念,都是数值,要么是8位的,要么是16位或32位的,就是一串二进制的值。它代表的是什么,由你来决定。
; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
DlgName db "MyDialog",0
szCaption db "提示",0
szFormat01 db "得到的数值是 %d",0
szText01 db "ABCDE",0
.data?
hInstance HINSTANCE ?
.const
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
ICO_MAIN equ 1000 ;图标
IDB01 equ 11 ;按钮控件标识符
IDB02 equ 12
IDB03 equ 13
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL @szBuffer01[256]:byte
LOCAL @szBuffer02[256]:byte
.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
.elseif uMsg == WM_COMMAND
mov eax,wParam
.if eax == IDB01
invoke AProc ;调用无参函数AProc
inc eax
invoke wsprintf,addr @szBuffer01,addr szFormat01 ,eax
invoke MessageBox,hWnd,addr @szBuffer01,addr szCaption,MB_OK
.elseif eax == IDB02
invoke BProc,1,2 ;调用有参函数BProc并给参数赋值
inc eax ;eax加1.因为返回值是3,再加1,则结果为4
invoke wsprintf,addr @szBuffer01,addr szFormat01 ,eax
invoke MessageBox,hWnd,addr @szBuffer01,addr szCaption,MB_OK
.elseif eax == IDB03
invoke lstrcpy,addr @szBuffer02,addr szText01 ;这里是多此一举,本来可以直接定义一个全局字符数组,就不用在函数里面要地址传进去又传出来。这里这样做,是为了说明这种逻辑,理解这种意思
invoke CProc,addr @szBuffer02 ;调用函数,把地址值,或者说指针当参数传进去,其返回值也是地址值
invoke MessageBox,hWnd,eax,addr szCaption,MB_OK
.endif
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
AProc proc ;无参数函数实体,因为前面进行了声明,所以可以放调用的后面
mov eax,1 ;返回值放eax里面。这是默认的,因为很多的时候,在调用此函数时,可能还调用了其它系统内的函数。如果返回值放其它寄存器,会导致混乱,其它的寄存器不一定是空值,可能在使用中。
ret
AProc endp
BProc proc A:DWORD,B:DWORD
mov eax,A
mov ebx,B
add eax,ebx ;A是1,B是2,加了后值在eax里,而eax是返回值
ret
BProc endp
CProc proc A:DWORD
mov esi,A ;让esi指向A地址的内容
mov al,byte ptr [esi+1] ;把第2个字符复制过来再覆盖第1个字符
mov byte ptr [esi],al
mov eax,esi ;把地址给eax,成为返回值
ret
CProc endp
end start
;下面为rc文件内容
#include "resource.h" //提示缺少该文件,可以在资源里下载
#define ICO_MAIN 1000 //图标
#define IDB01 11
#define IDB02 12
#define IDB03 13
ICO_MAIN ICON "Main.ico"
//定义对话框
MyDialog DIALOG 10, 10, 120, 100
STYLE DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "对话框程序模版"
BEGIN
PUSHBUTTON "调用无参函数AProc", IDB01, 10,20,100,14
PUSHBUTTON "调用有参函数BProc", IDB02, 10,40,100,12
PUSHBUTTON "调用带指针参数的函数BProc", IDB03, 10,60,100,14
END