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
?
?
?