Win32汇编——过程控制(环境变量、命令行参数、可执行文件执行)

本文介绍了在Win32汇编中如何处理过程控制,包括获取环境变量、处理命令行参数以及理解可执行文件的执行流程。特别地,由于Windows NT系统中CommandLineToArgvW函数的限制,文章提供了一个自定义的通用命令行参数获取函数的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.环境变量
按用途可分为:与系统运行相关、反应系统状态以及应用程序自定义三种环境变量
操作函数:
获取一个环境变量的值:GetEnvironmentVariable
设置新变量或删除已有变量 :SetEnvironmentVariable (仅改变本进程的环境变量)
枚举所有的环境变量:GetEnvironmentStrings
释放环境变量的拷贝:FreeEnvironmentStrings

2.命令行参数:某些情况下,命令行参数是窗口程序的必然补充,如:关联文件
操作函数:
获取命令行参数:GetCommanLine (Windows以空格区分参数,所以应注意双引号引起的问题)

PS:Win32中CommandLineToArgvW 可以扫描字符串,但仅适合Unicode 和 WinNT ,因此,我们自己编写一个获取命令行参数的通用函数,代码如下:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; _CmdLine.asm
; 命令行参数分析的通用子程序
; 功能:
; _argc ---> 对命令行参数进行数量统计
; _argv ---> 取某个命令行参数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CHAR_BLANK	equ	20h	;定义空格
CHAR_DELI	equ	'"'	;定义分隔符
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 取命令行参数个数 (arg count)
; 参数个数必定大于等于 1, 参数 1 为当前执行文件名
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_argc		proc
		local	@dwArgc		;参数个数

		pushad
		mov	@dwArgc,0
		invoke	GetCommandLine
		mov	esi,eax
		cld
_argc_loop:
;********************************************************************
; 忽略参数之间的空格
;********************************************************************
		lodsb
		or	al,al
		jz	_argc_end		;无输入或到字符串尾
		cmp	al,CHAR_BLANK
		jz	_argc_loop		;空格则忽略
;********************************************************************
; 一个参数开始
;********************************************************************
		dec	esi				;
		inc	@dwArgc
_argc_loop1:
		lodsb
		or	al,al
		jz	_argc_end		;无输入或到字符串尾
		cmp	al,CHAR_BLANK
		jz	_argc_loop		;空格则忽略
		cmp	al,CHAR_DELI
		jnz	_argc_loop1		;引号,继续处理参数内容
;********************************************************************
; 如果一个参数中的一部分有空格,则用 " " 包括
;********************************************************************
		@@:
		lodsb
		or	al,al
		jz	_argc_end		;无输入或到字符串尾
		cmp	al,CHAR_DELI	;直到遇到另一个引号为止
		jnz	@B
		jmp	_argc_loop1
_argc_end:
		popad
		mov	eax,@dwArgc
		ret

_argc		endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 取指定位置的命令行参数
;  argv 0 = 执行文件名
;  argv 1 = 参数1 ...
; 参数含义:参数编号,接收参数缓冲区,缓冲区大小
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_argv		proc	_dwArgv,_lpReturn,_dwSize
		local	@dwArgv,@dwFlag

		pushad
		inc	_dwArgv
		mov	@dwArgv,0
		mov	edi,_lpReturn	;目的串

		invoke	GetCommandLine
		mov	esi,eax
		cld
_argv_loop:
;********************************************************************
; 忽略参数之间的空格
;********************************************************************
		lodsb
		or	al,al
		jz	_argv_end
		cmp	al,CHAR_BLANK
		jz	_argv_loop		;同上
;********************************************************************
; 一个参数开始
; 如果和要求的参数符合,则开始复制到返回缓冲区
;********************************************************************
		dec	esi
		inc	@dwArgv
		mov	@dwFlag,FALSE
		mov	eax,_dwArgv
		cmp	eax,@dwArgv
		jnz	@F
		mov	@dwFlag,TRUE	;表示需要将字符返回
		@@:
_argv_loop1:
		lodsb
		or	al,al
		jz	_argv_end
		cmp	al,CHAR_BLANK
		jz	_argv_loop		;参数结束
		cmp	al,CHAR_DELI
		jz	_argv_loop2
		cmp	_dwSize,1		;如果返回缓冲区满则返回
		jle	@F
		cmp	@dwFlag,TRUE
		jne	@F
		stosb
		dec	_dwSize
		@@:
		jmp	_argv_loop1		;继续处理参数内容

_argv_loop2:
		lodsb
		or	al,al
		jz	_argv_end
		cmp	al,CHAR_DELI
		jz	_argv_loop1
		cmp	_dwSize,1		;如果返回缓冲区满则返回
		jle	@F
		cmp	@dwFlag,TRUE
		jne	@F
		stosb
		dec	_dwSize
		@@:
		jmp	_argv_loop2
_argv_end:
		xor	al,al
		stosb				;0结束
		popad
		ret

_argv		endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
3.可执行文件的执行
3.1 Shell 调用(创建了新进程,但控制不了)
WinExec
ShellExecute
3.2 创建进程(可进行后续控制)
进程被创建时,系统的操作:创建一个内核对象和一个虚拟地址空间以及一个主线程


涉及结构:
STARTUPINFO
PROCESS_INFORMATION
涉及函数:
获取当期进程的 STARTUPINFO :GetStartUp
创建进程:CreateProcess
结束进程:ExitProcess
获取退出码:GetExitCodeProcess
结束其他进程:TerminateProcess


进程被结束时,系统的操作:
(1)关闭进程创建或打开的所有对象句柄
(2)终止进程中的所有线程
(3)进程及进程中所有线程的状态被改为置位状态,以便让WaitSingleObject 函数正确检测
(4)进程对象中的退出码字段从 STILL_ACTIVE 被改为指定的退出码


PS:进程结束不影响子进程,直到使用CloseHandle 将进程句柄关闭后,进程对象才真正被删除。当不再需要进程句柄的时候,记得关闭PROCESS_INFORMATION结构中返回的进程句柄和主线程句柄。
示例如下:
		.data?
stStartUp	STARTUPINFO		<?>
stProcInfo	PROCESS_INFORMATION	<?>

		.code
invoke	lstrcpy,addr @szBuffer,addr szFileName
		.if	szCmdLine
			invoke	lstrcat,addr @szBuffer,addr szBlank
			invoke	lstrcat,addr @szBuffer,addr szCmdLine
		.endif
;********************************************************************
; 创建进程
;********************************************************************
		invoke	GetStartupInfo,addr stStartUp
		invoke	CreateProcess,NULL,addr @szBuffer,NULL,NULL,NULL,\
			NORMAL_PRIORITY_CLASS,NULL,NULL,addr stStartUp,addr stProcInfo
		.if	eax
;********************************************************************
; 等待进程结束
;********************************************************************
			invoke	WaitForSingleObject,stProcInfo.hProcess,INFINITE
			invoke	CloseHandle,stProcInfo.hProcess
			invoke	CloseHandle,stProcInfo.hThread
		.else
			invoke	MessageBox,hWinMain,addr szErrExec,NULL,MB_OK or MB_ICONWARNING
		.endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值