在编写窗口程序的时候,经常需要使用messagebox函数,不管是调试输入也好,查看变量也罢。这时如果是全字符串的还好,但是如果需要显示数值的内容时,用这个函数就比较麻烦了。需要先使用wsprintf函数执行一遍,然后在使用messagebox函数。远没有在命令行下的printf方便,如果是需要大量弹窗时就更麻烦了。所以决定将这两个函数封装起来,这样messagebox就可以和printf函数一样方便使用了。最终经过两天时间,完成了这个Unicode编码的函数,期间碰到了许多问题,通过一次次单步调试,查看汇编代码最终解决掉了所有问题,函数能正常使用了。
源码
/*-------------------------------------------------------*/
/* 函数名称: 御坂高级弹窗消息 - 限长2000限参100 Unicode
/* 函数参数: 第一个是字符串,和printf一样,不定参数个数
/* 使用说明: 弹窗的内容可以使用任意多个参数,类型暂时只支持 %d 和 %s
/*-------------------------------------------------------*/
VOID MSKMessageBox(PTSTR string, ...){
UINT num = 0;
__asm{//获取字符串的长度,Unicode版本
//int 3
mov eax, string//获得字符串的地址
sss:
xor ebx,ebx//清零寄存器
mov bx,word ptr [eax]//获取该地址的两字节的值,赋值给bx
add num,1//计数+1
add eax, 2//地址偏移+2
test bx, bx//判断bx是不是为0
jne sss//如果不是0则循环
}
TCHAR str[2001] = {0};//最多2000的字节内容,如果超过2000就返回错误
DWORD straddress[100] = { 0 };//字符串参数地址,最多100个
INT param = 0;//参数个数
INT strnum = 0;//新的字符串的计数
INT arrnum = 0;//数组的计数
DWORD ebpnum = 0;//先获得EBP的基址
DWORD temp;//用来获取数字的值的
UINT i;
for (i = 0; i< num&& i< 2000; i++){
if (string[i] == '%' && (string[i + 1] == 'd' || string[i + 1] == 's')){
param++;
__asm{
mov dword ptr[ebpnum], ebp
}
if (string[i] == '%' && string[i + 1] == 'd'){
TCHAR number[11] = { 0 };//INT整数最多10位
temp = ebpnum + 4 * param + 8;
wsprintf(number, TEXT("%d"), *(DWORD*)temp);
int test = 0;
test = lstrlen(number);
memcpy(&str[strnum], number, lstrlen(number) * 2);//unicode
strnum += lstrlen(number);
i++;
} else{
//--------------------------------------------
temp = ebpnum + 4 * param + 8;//取得参数的地址,然后4字节的值写入到对应位置
straddress[arrnum] = *(DWORD*)temp;
int testnum = 0;
__asm{//获取字符串的长度,Unicode版本
mov ecx, arrnum
mov eax, straddress
mov eax, straddress[ecx * 4]
sss2 :
xor ebx, ebx
mov bx, word ptr[eax]
add testnum, 1
add eax, 2
test bx, bx
jne sss2
dec testnum
}
memcpy(&str[strnum], straddress[arrnum], testnum * 2);//unicode
strnum += testnum;
i++;
arrnum++;
//--------------------------------------------
}
} else{
str[strnum] = string[i];
strnum += 1;
}
}
TCHAR msg[2001] = {0};
wsprintf(msg, TEXT("字符串:%s 长度:%d 参数:%d"), str, lstrlen(str), param);
MessageBox(NULL, msg, TEXT("御坂高级弹窗消息"), MB_OK);
}