news 2026/4/18 7:53:12

汇编语言全接触-67.Win32汇编教程十一

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇编语言全接触-67.Win32汇编教程十一

在这儿下载本节的所有源程序

概述

进程控制简单的说相当于在一个程序中执行另一个程序,你可以把它想象成在 Dos 下用 int 21h/4bh 功能来执行另外一个程序,如果单从执行另一个程序的目的来讲,在 Windows 中有不少方法,如使用 ShellExecute 等,但这些 Api 仅仅是“执行”而已,进程控制的意义在于可以创建一个进程,并可以通过进程句柄结束进程,同样你也可以通过进程句柄来跟踪程序,还可以用 ReadProcessMemory 和 WriteProcessMemory 来读写子进程的内存空间。

进程控制要使用的相关 API 有下面这些:

创建进程的函数为CreateProcess,该函数比较复杂,共有十个参数,但有个好消息是使用时大部分可以用 NULL。

BOOL CreateProcess(

LPCTSTR lpApplicationName, // 执行程序文件名

LPTSTR lpCommandLine, // 参数行

LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全参数

LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全参数

BOOL bInheritHandles, // 继承标记

DWORD dwCreationFlags, // 创建标记

LPVOID lpEnvironment, // 环境变量

LPCTSTR lpCurrentDirectory, // 运行该子进程的初始目录

LPSTARTUPINFO lpStartupInfo, // 创建该子进程的相关参数

LPPROCESS_INFORMATION lpProcessInformation // 创建后用于被创建子进程的信息

);

各个参数的说明如下:

lpApplicationName:为执行程序的文件名,你也可以把执行文件名包括在下一个参数 lpCommandLine 中,然后把该参数置为NULL。

lpCommandLine:为参数行,如果无参数可以为NULL,在有参数传递给进程时可以如下设置:lpApplicationName=文件名;lpCommandLine=参数,或者 lpApplicationName=NULL;lpCommandLine=文件名 + 参数。

lpProcessAttributes,lpThreadAttributes:分别描述了创建的进程和线程安全属性,如果使用NULL表示使用默认的安全描述。

bInheritHandles:表示当前进程中的打开的句柄是否能够被创建的子进程所继承。

dwCreationFlags:表示创建标记,通过该标记可以设置进程的创建状态和优先级别。常用的有下面的标记:

CREATE_NEW_CONSOLE:为子进程创建一个新的控制台。

CREATE_SUSPENDED:子进程在创建时为挂起状态。如果指定了这个参数,那么执行 CreateProcess 后进程只是被装入内存,但不是马上开始执行,而是必须等主程序调用 ResumeThread 后才继续执行。

HIGH_PRIORITY_CLASS/NORMAL_PRIORITY_CLASS:高/普通优先级别。

lpEnvironment:表示子进程所使用的环境变量,如果为NULL,则表示与当前进程使用相同的环境变量。

lpCurrentDirectory:表示子进程运行的初始目录。

lpStartupInfo:STARTUPINFO 结构,用于在创建子进程时设置各种属性。

lpProcessInformation:PROCESS_INFORMATION 结构,用来在进程创建后接收相关信息,该结构由系统填写。

调用 CreateProcess 函数有三个参数是必需的,一在 lpApplicationName 或 lpCommandLine 指定文件名,二是 lpStartupInfo 结构,三是 PROCESS_INFORMATION 结构,因为 PROCESS_INFORMATION 结构返回了进程建立后的句柄,以后的一切操作将要用到这些返回的句柄,它是由系统填写的,结构说明如下:

typedef struct _PROCESS_INFORMATION {

HANDLE hProcess; //进程句柄

HANDLE hThread; //进程的主线程句柄

DWORD dwProcessId; //进程ID

DWORD dwThreadId; //进程的主线程ID

} PROCESS_INFORMATION;

另外还有一个关键的结构 STARTUPINFO,该结构定义如下:

typedef struct STARTUPINFO {

DWORD cb; //结构长度

LPTSTR lpReserved; //保留

LPTSTR lpDesktop; //保留

LPTSTR lpTitle; //如果为控制台进程则为显示的标题

DWORD dwX; //窗口位置

DWORD dwY; //窗口位置

DWORD dwXSize; //窗口大小

DWORD dwYSize; //窗口大小

DWORD dwXCountChars; //控制台窗口字符号宽度

DWORD dwYCountChars; //控制台窗口字符号高度

DWORD dwFillAttribute; //控制台窗口填充模式

DWORD dwFlags; //创建标记

WORD wShowWindow; //窗口显示标记,如同ShowWindow中的标记

WORD cbReserved2; //

LPBYTE lpReserved2; //

HANDLE hStdInput; //标准输入句柄

HANDLE hStdOutput; //标准输出句柄

HANDLE hStdError; //标准错误句柄

} STARTUPINFO, *LPSTARTUPINFO;

结构中 dwFlags 指定了其它的一些字段是否有效,如:dwFlags包含 STARTF_USESIZE 表示dwXSize和dwYSize有效,包含STARTF_USEPOSITION表示dwX和dwY有效,等等。如果不是有特殊的要求,我们不用自己去填写这个结构,只需用 GetStartupInfo 让 Windows 为你填写好了,这样,建立一个进程的语句就是:

...

stStartUp STARTUPINFO stProcInfo PROCESS_INFORMATION <?>

stProcInfo PROCESS_INFORMATION <?>

...

invoke GetStartupInfo,addr stStartUp

invoke CreateProcess,NULL,addr szFileName,NULL,NULL,NULL,NORMAL_PRIORITY_CLASS,NULL,NULL,offset stStartUp,offset stProcInfo

...

如果成功的话,eax 将返回非零值,注意返回在 PROCESS_INFORMATION 结构中的 hProcess,以后很多的操作都要用到它。

强制结束一个进程的 API 为 TerminateProcess

BOOL TerminateProcess(

HANDLE hProcess, // 进程句柄

UINT uExitCode // 退出代码

);

你可以使用语句 invoke TerminateProcess,structProcInfo.hProcess,0 来结束进程,要注意的是如果可能的话,尽量不要在程序中强制结束别的进程,因为使用 TerminateProcess 结束的进程,它装载的 dll 不能被正确卸载。这样可能会引起系统资源的无效占用。最好的办法在进程中自己使用 ExitProcess 退出。

查询一个进程状态的 API 为 GetExitCodeProcess。

BOOL GetExitCodeProcess(

HANDLE hProcess, // handle to the process

LPDWORD lpExitCode // address to receive termination status

);

如果进程尚未退出,函数将会返回STILL_ACTIVE。这个 API 是马上返回的。

等待进程执行可以用 WaitForSingleObject

这个 API 并不是单用于进程的等待,其它还可以用在线程等操作,但我们一般用它来等待进程的执行,它的申明是:

DWORD WaitForSingleObject(

HANDLE hHandle, // handle of object to wait for

DWORD dwMilliseconds // time-out interval in milliseconds

);

如果我们要等待进程执行 1 秒钟,可以 invoke WaitForSingleObject,stProcInfo.hProcess,1000 如果要等到进程结束,可以用 WaitForSingleObject,stProcInfo.hProcess,INFINITE ,参数 2 中的 INFINITE 在 Windows.inc 中有定义,意思是无穷等待。

最后,当不再使用进程句柄的时候,不要忘了使用 CloseHandle 关闭 hProcess 和 hThread,否则会浪费系统句柄的资源。

源程序 - 汇编源文件

.386

.model flat, stdcall

option casemap :none ; case sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 数据

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include windows.inc

include user32.inc

include kernel32.inc

include comctl32.inc

include comdlg32.inc

include gdi32.inc

includelib user32.lib

includelib kernel32.lib

includelib comctl32.lib

includelib comdlg32.lib

includelib gdi32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Equ 数据

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DLG_MAIN equ 3000

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ID_BROWSE equ 3001

ID_RUN equ 3002

ID_EXIT equ 3003

ID_TEXT equ 3004

F_RUNNING equ 0001h ;进程在运行中

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 数据段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.data?

stStartUp STARTUPINFO <?>

stProcInfo PROCESS_INFORMATION <?>

stOpenFileName OPENFILENAME <?>

hRunThread dd ?

hInstance dd ?

hWinMain dd ?

hIcon dd ?

szBuffer db 512 dup (?)

dwFlag dd ?

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.data

szExcute db '执行(&E)',0 ;按钮文字

szKill db '终止(&E)',0

szExcuteError db '启动应用程序错误!',0

szTitleOpen db "Open executable file...",0

szExt db '*.exe',0

szFilter db 'Excutable Files',0,'*.exe;*.com',0

db 0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 代码段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.code

if DEBUG

include Debug.asm

endif

include Win.asm

;********************************************************************

; 执行程序用的线程

; 1. 用 CreateProcess 建立进程

; 2. 用 WaitForSingleOject 等待进程结束

;********************************************************************

_RunThread proc uses ebx ecx edx esi edi,\

dwParam:DWORD

or dwFlag,F_RUNNING

;********************************************************************

; 取消“退出”按钮并把“执行”按钮改为“中止”

;********************************************************************

invoke GetDlgItem,hWinMain,ID_EXIT

invoke EnableWindow,eax,FALSE

invoke SendDlgItemMessage,hWinMain,ID_RUN,WM_SETTEXT,0,offset szKill

;********************************************************************

; 执行文件,如果成功则等待程序结束

;********************************************************************

invoke GetStartupInfo,addr stStartUp

invoke CreateProcess,NULL,addr szBuffer,NULL,NULL,\

NULL,NORMAL_PRIORITY_CLASS,NULL,NULL,offset stStartUp,offset stProcInfo

.if eax != 0

invoke WaitForSingleObject,stProcInfo.hProcess,INFINITE

invoke CloseHandle,stProcInfo.hProcess

invoke CloseHandle,stProcInfo.hThread

.else

invoke MessageBox,hWinMain,addr szExcuteError,NULL,MB_OK or MB_ICONERROR

.endif

;********************************************************************

; Enable “退出”按钮并把“中止”按钮改为“执行”

;****************************************

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 2:27:36

汇编语言全接触-68.Win32汇编教程十二

在这儿下载本节的所有源程序 概述 Windows 引入了多进程和多线程机制。同时也提供了多个进程之间的通信手段&#xff0c;包括剪贴板、DDE、OLE、管道等&#xff0c;和其他通信手段相比&#xff0c;管道有它自己的限制和特点&#xff0c;管道实际上是一段共享内存区&#xff0…

作者头像 李华
网站建设 2026/4/18 2:34:28

2026 GEO优化服务商TOP5测评榜:谁能真正解决企业AI推广核心痛点

随着生成式AI全面重构流量逻辑&#xff0c;GEO&#xff08;生成式引擎优化&#xff09;已成为企业抢占AI流量入口的核心抓手。但市场上服务商良莠不齐&#xff0c;GEO优化服务商哪家好、如何让AI推广我的品牌、GEO优化运营商哪家靠谱成为企业决策的高频疑问。本次测评基于第三方…

作者头像 李华
网站建设 2026/4/17 12:48:11

如何让AI推广我的品牌?成长期企业GEO优化全攻略

对于成长期企业而言&#xff0c;“如何让AI推广我的品牌”早已成为突破增长瓶颈的核心疑问。不少企业尝试GEO优化却频频碰壁&#xff1a;要么投入大量预算后&#xff0c;AI平台曝光量寥寥无几&#xff1b;要么跨境推广时触碰合规红线&#xff0c;面临巨额罚款&#xff1b;要么优…

作者头像 李华
网站建设 2026/4/18 2:34:28

揭秘PHP容器中环境变量的致命陷阱:90%开发者都忽略的3个细节

第一章&#xff1a;PHP容器中环境变量的致命陷阱概述在现代PHP应用部署中&#xff0c;Docker容器已成为标准实践。然而&#xff0c;环境变量作为容器化配置的核心机制&#xff0c;常因使用不当引发严重问题。最常见的陷阱包括变量未正确加载、类型误解、敏感信息泄露以及运行时…

作者头像 李华
网站建设 2026/4/18 2:34:56

GLM-TTS部署避坑指南:显存占用、采样率与KV Cache优化技巧

GLM-TTS部署避坑指南&#xff1a;显存占用、采样率与KV Cache优化技巧 在构建语音合成服务的实践中&#xff0c;我们常常以为模型一旦训练完成&#xff0c;部署就是“一键启动”的简单过程。现实却往往相反——尤其是面对像 GLM-TTS 这类基于大语言模型架构的端到端语音生成系统…

作者头像 李华