使用C库函数

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
.386
.model flat,stdcall
OPTION CASEMAP:none

include msvcrt.inc
include kernel32.inc

includelib user32.lib
includelib kernel32.lib
includelib msvcrt.lib;包含动态库
;includelib libc.lib;包含静态库

.const
MY_STRING db "51asm51asm:%d",0dh,0ah,0
MY_PAUSE db "pause",0

;代码区
.code

myadd proc
ret
myadd endp

strlen proto c:dword
printf proto c:VARARG

START proc
;C库的使用 c调用约定
local buf1[10]:byte
local buf2[10]:byte

;invoke strlen,offset MY_STRING
;invoke printf,offset MY_STRING

;push offset MY_STRING
;call printf
;add esp,4

;invoke myadd,1,2,3
;push 3
;push 2
;push 1
;call myadd
;add esp,12

invoke crt_strcpy,addr buf1,offset MY_STRING
invoke crt_strcpy,addr buf2,offset MY_STRING
invoke crt_printf,offset MY_STRING,10
invoke crt_system,offset MY_PAUSE
invoke ExitProcess,0
ret
START endp

end START

指令集和模型设置

1
2
3
.386
.model flat,stdcall
OPTION CASEMAP:none
  • **.386**:指定代码针对80386处理器编写,这是一个32位处理器。
  • **.model flat,stdcall**:指定内存模型为平坦(flat),调用约定为stdcall,即所有的内存视为一个单一段。
  • **OPTION CASEMAP:none**:指定汇编器对所有标签和符号区分大小写,不自动转换大小写。

包含头文件

1
2
include msvcrt.inc
include kernel32.inc
  • **include msvcrt.inc**:包含MSVCRT库(Microsoft Visual C Runtime Library)的函数声明和宏。
  • **include kernel32.inc**:包含Kernel32库(Windows内核库)的函数声明和宏。

链接动态库

1
2
3
includelib user32.lib
includelib kernel32.lib
includelib msvcrt.lib
  • **includelib user32.lib**:链接用户界面相关的User32库。
  • **includelib kernel32.lib**:链接与操作系统核心功能相关的Kernel32库。
  • **includelib msvcrt.lib**:链接C运行时库MSVCRT的动态库。

定义常量

1
2
3
.const
MY_STRING db "51asm51asm:%d",0dh,0ah,0
MY_PAUSE db "pause",0
  • **MY_STRING**:定义一个字符串常量,内容是”51asm51asm:%d”,后面跟着回车换行符0dh, 0ah和字符串终止符0
  • **MY_PAUSE**:定义一个字符串常量,内容是”pause”,用于暂停命令行窗口。

函数定义

1
2
3
myadd proc
ret
myadd endp
  • **myadd**:定义一个空函数myadd,使用proc关键字开始函数,ret指令返回到调用者,endp结束函数定义。

外部函数声明

1
2
strlen proto c:dword
printf proto c:VARARG
  • **strlen**:声明C库函数strlen,用于计算字符串长度。
  • **printf**:声明C库函数printf,用于格式化输出。VARARGprintf 等函数的一个特殊调用约定,用于表示该函数可以接受可变数量的参数。

主程序开始

1
2
3
START proc
local buf1[10]:byte
local buf2[10]:byte
  • **START proc**:定义程序入口START
  • **local buf1[10]:bytelocal buf2[10]:byte**:定义两个局部字节数组buf1buf2,各自长度为10个字节。
1
2
;invoke strlen,offset MY_STRING
;invoke printf,offset MY_STRING
  • 这些注释掉的代码原本是调用strlenprintf函数,但当前未执行。

调用库函数

1
2
3
4
invoke crt_strcpy,addr buf1,offset MY_STRING
invoke crt_strcpy,addr buf2,offset MY_STRING
invoke crt_printf,offset MY_STRING,10
invoke crt_system,offset MY_PAUSE
  • **invoke crt_strcpy,addr buf1,offset MY_STRING**:将MY_STRING复制到buf1中,调用的是C库的strcpy函数。
  • **invoke crt_strcpy,addr buf2,offset MY_STRING**:将MY_STRING复制到buf2中,调用同样的strcpy函数。
  • **invoke crt_printf,offset MY_STRING,10**:使用C库的printf函数输出格式化字符串MY_STRING,参数为10
  • **invoke crt_system,offset MY_PAUSE**:调用系统命令pause,暂停命令行窗口的关闭。

程序结束

1
2
3
invoke ExitProcess,0
ret
START endp
  • **invoke ExitProcess,0**:调用ExitProcess函数退出程序,返回值为0
  • **ret**:从程序入口返回。
  • **START endp**:结束程序入口的定义。

运行结果

image-20240831215355984

调用对话框

新建对话框

image-20240831204736684

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
.386
.model flat,stdcall
OPTION CASEMAP:none

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

includelib user32.lib
includelib kernel32.lib
includelib msvcrt.lib;包含动态库
;includelib libc.lib;包含静态库

IDD_DIALOG1 EQU 101

.const
MY_STRING db "51asm51asm:%d",0dh,0ah,0
MY_PAUSE db "pause",0

;代码区
.code
DialogProc PROC hwndDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_CLOSE
invoke EndDialog,hwndDlg,0
mov eax,TRUE
ret
.endif
mov eax,FALSE
ret
DialogProc endp

START proc
local @hInstance:HINSTANCE
invoke GetModuleHandle,NULL
mov @hInstance,eax
invoke DialogBoxParam,@hInstance,IDD_DIALOG1,NULL,OFFSET DialogProc,NULL
invoke ExitProcess,0
ret
START endp

end START

这段代码是一个汇编程序,使用Win32 API创建了一个简单的对话框应用程序。下面是每一行代码的详细解释:

指令集和模型设置

1
2
3
.386
.model flat,stdcall
OPTION CASEMAP:none
  • **.386**:指定代码是为80386处理器编写的,这是一个32位的处理器。
  • **.model flat,stdcall**:指定内存模型为平坦(flat),调用约定为stdcall,即所有的内存视为一个单一段。
  • **OPTION CASEMAP:none**:指定汇编器对所有标签和符号区分大小写,不自动转换大小写。

包含头文件

1
2
3
4
include msvcrt.inc
include kernel32.inc
include user32.inc
include windows.inc
  • **include msvcrt.inc**:包含MSVCRT库(Microsoft Visual C Runtime Library)的函数声明和宏。
  • **include kernel32.inc**:包含Kernel32库(Windows内核库)的函数声明和宏。
  • **include user32.inc**:包含User32库(用户界面相关的Windows API)的函数声明和宏。
  • **include windows.inc**:包含Windows API的基本数据类型和常量的定义。

链接动态库

1
2
3
4
includelib user32.lib
includelib kernel32.lib
includelib msvcrt.lib;包含动态库
;includelib libc.lib;包含静态库
  • **includelib user32.lib**:链接用户界面相关的User32库。
  • **includelib kernel32.lib**:链接与操作系统核心功能相关的Kernel32库。
  • **includelib msvcrt.lib**:链接C运行时库MSVCRT的动态库。
  • includelib libc.lib (被注释掉):这是静态库的链接声明,已被注释,不实际使用。

定义常量

1
IDD_DIALOG1 EQU 101
  • **IDD_DIALOG1 EQU 101**:定义一个对话框资源ID,值为101。这是对话框资源的唯一标识符。
1
2
3
.const
MY_STRING db "51asm51asm:%d",0dh,0ah,0
MY_PAUSE db "pause",0
  • **MY_STRING**:定义一个字符串常量,内容是 "51asm51asm:%d",后面跟着回车换行符 0dh, 0ah 和字符串终止符 0
  • **MY_PAUSE**:定义一个字符串常量,内容是 "pause",用于暂停命令行窗口。

对话框处理过程

1
2
3
4
5
6
7
8
9
DialogProc PROC hwndDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_CLOSE
invoke EndDialog,hwndDlg,0
mov eax,TRUE
ret
.endif
mov eax,FALSE
ret
DialogProc endp
  • **DialogProc**:定义一个对话框过程函数,用于处理对话框的消息。
  • **hwndDlg:HWND**:对话框窗口的句柄。
  • **uMsg:UINT**:消息的类型。
  • wParam:WPARAM 和 **lParam:LPARAM**:消息的附加参数。
  • **IF uMsg==WM_CLOSE**:检查接收到的消息是否是 WM_CLOSE,即关闭对话框的消息。
    • **invoke EndDialog,hwndDlg,0**:调用 EndDialog 函数关闭对话框,返回值为0
    • **mov eax,TRUE**:将返回值设为 TRUE,表示消息已处理。
    • **ret**:返回到调用者。
  • **mov eax,FALSE**:如果消息不是 WM_CLOSE,则返回 FALSE,表示消息未处理。
  • **DialogProc endp**:结束对话框过程函数的定义。

主程序开始

1
2
3
4
5
6
7
8
START proc
local @hInstance:HINSTANCE
invoke GetModuleHandle,NULL
mov @hInstance,eax
invoke DialogBoxParam,@hInstance,IDD_DIALOG1,NULL,OFFSET DialogProc,NULL
invoke ExitProcess,0
ret
START endp
  • **START proc**:定义程序的入口函数 START

  • **local @hInstance:HINSTANCE**:定义一个局部变量 @hInstance,类型为 HINSTANCE,用于存储当前模块的实例句柄。

  • **invoke GetModuleHandle,NULL**:调用 GetModuleHandle 函数获取当前模块的实例句柄,并将其存储在 @hInstance 中。

  • **mov @hInstance,eax**:将函数返回值(当前模块的句柄)存储在 @hInstance 中。

  • **invoke DialogBoxParam,@hInstance,IDD_DIALOG1,NULL,OFFSET DialogProc,NULL**:调用 DialogBoxParam 函数创建并显示对话框。参数分别为:

    • @hInstance:当前模块的实例句柄。
    • IDD_DIALOG1:对话框的资源ID。
    • NULL:父窗口句柄(无父窗口)。
    • OFFSET DialogProc:对话框过程函数的地址。
    • NULL:传递给对话框过程函数的附加参数(无)。

    image-20240831215827697

  • **invoke ExitProcess,0**:调用 ExitProcess 函数终止程序,返回值为0

  • **ret**:返回到调用者。

  • **START endp**:结束程序入口函数的定义。

运行结果

image-20240831220035463