Win32ASM && 变长参数的理解

C语言里面 提供了一些宏  可以使用变长参数

 

int MsgPrintf(INT dwszBuffer,TCHAR* szCaption,TCHAR* szFormat,...)
{
	LPVOID lpszBuffer;
	va_list	pArgList;
	va_start(pArgList,szFormat);
	lpszBuffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,100);
	_vsntprintf((LPTSTR)lpszBuffer,dwszBuffer/sizeof (TCHAR),szFormat,pArgList);
	va_end(pArgList);
	return MessageBox(NULL,(LPTSTR)lpszBuffer,szCaption,MB_OK);
}

 

如果要知道变长参数的长度  就不得不在传一个参数来进行标识了

 

因为是C语言调用方式,所以栈由调用者来平衡  也就是add esp,xxh   这个xxx也就是参数的总长度

add esp,xxh会被解释成      83h 4ch xxh   也就是函数返回地址  加上2  就是参数的总字节数了

C语言测试代码如下

 

int Test(int a,int b,...)
{
	int dwSizeOfPar;
	int *p = &a;
	dwSizeOfPar = *((int *)*(p - 1));
	dwSizeOfPar = ((dwSizeOfPar >> 16) & 0x0FF) >> 2;
	return dwSizeOfPar;
}


根据这个原理  写了一个   Win32ASM版本的格式化输出

 

_MsgBoxPrintf proc C _dwSizeOfBuff:DWORD,_lpszCaption:DWORD,_lpszFormat:DWORD,_varg:VARARG
	LOCAL	@hProcessHeap:DWORD 
	LOCAL	@lpszBuffer:DWORD 
	LOCAL	@dwSizePar:DWORD
	
	lea		eax,_dwSizeOfBuff
	mov		eax,[eax - 4]				;获取函数的返回地址
	movzx	eax,byte ptr [eax + 2]		;获取参数总字节数
	shr		eax,2					;获取参数个数
	;没有传递不定参数,作为默认处理
	cmp 		eax,3	
	jnb		@F
	
	sub		eax,3
	mov		@dwSizePar,eax				
	invoke	GetProcessHeap
	mov		@hProcessHeap,eax
	invoke	HeapAlloc,@hProcessHeap,HEAP_ZERO_MEMORY,_dwSizeOfBuff 
	mov		@lpszBuffer,eax
	
	.while	@dwSizePar
		lea	esi,_varg
		mov	ebx,@dwSizePar
		sub	ebx,1
		mov eax,[esi + ebx * 4]
		push	eax
		dec	@dwSizePar
	.endw
	push		_lpszFormat
	push		@lpszBuffer
	call		wsprintf
	invoke	MessageBox,NULL,@lpszBuffer,_lpszCaption,MB_OK
	ret
	@@:
	invoke	MessageBox,NULL,_lpszFormat,_lpszCaption,MB_OK
	ret

_MsgBoxPrintf endp 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值