一、wsprintf 声明(一般都都在包含文件中定义)
//显然,在汇编源文件中涉及的以 inc 为扩展名的文件一般为包含文件,由此可知,inc 是 include(包含)的缩写了。
windows.inc 中是这样描述的:
IFNDEF _wininc_ ;如果没有定义_wininc_
_wininc_ equ <1> ;那么 _wininc_ 定义为 1
wsprintfA PROTO C :DWORD,:VARARG
wsprintf equ <wsprintfA>
ENDIF
由上面2个包含文件中的原型声明可知,wsprintf 与 wsprintfA 是等同的。
实际中基本所有函数都有2个版本,即 ANSI 版和 UNICODE(宽字符)版,命名规则上在函数名后冠以A和W来区分,wsprintf也不例外,同样有2
个版本,分别是 wsprintfA 和 wsprintfW
WINUSER.H 中是这样描述的:
//
#ifdef UNICODE ;如果定义为 UNICODE
#define wsprintf wsprintfW ;那么 wsprintf 就是 wsprintfW
#else ;否则
#define wsprintf wsprintfA ;定义wsprintf 就是 wsprintfA
#endif // !UNICODE
//
由上面的头定义中可以看出,通过上面对ANSI 和 UNICODE 2个版本的定义,我们在实际编程时源文件中为什么只用了 wsprintf 函数名而从没
使用 wsprintfW 和wsprintfA 的原因,你把自己编写的程序静态反汇编或动态调试时为什么只见到 wsprintfW 和 wsprintfA(如果你编写的程
序中调用了这个函数的话,没有调用这个函数你至少也得调用一个吧),
二、定义
1、int wsprintf(LPTSTR lpOut, // 输出缓冲区,最大为1024字节
LPCTSTR lpFmt, // 格式字符串
... //需输出参数列表,
由此可知,只有这个函数的参数个数无法确定,也是所有函数中的一个特例(无法确定参数
//个数的唯一函数),其他函数的参数个数是确定的,只此例外。
);
使用此函数可将数字转为字符串;
例:(C 语言源程序片断)
int x=6
LPTSTR szBuffer=new TCHAR[1024];
wsprintf(szBuffer,"%d",x); //将变量x的值格式化为数字(%d)输出到缓冲区szBuffer指向的内存单元。
MessageBox(NULL,szBuffer," ",MB_OK);
以下红色部分阐述的申明:
以下部分阐述是完全错误的,读者不予理会,保留的目的是楼下对这个部分给了纠正建议,特意保留以示对
pengmo 的尊重和对自己所犯严重错误不得原谅的“回报”。
int x=6;
LPTSTR szBuffer=new TCHAR[1024];
wsprintf(szBuffer,"%d",x); //将指向缓冲区szBuffer的数据格式化为数字(%d)并按6位(int x=6)输出,如果缓冲区数据的实际位数<6,位数不够部分的左侧填充空格(还是0)???来补足,如果缓冲区数据的实际位数>=6,按实际位数输出还是截去多余的位数输出???
MessageBox(NULL,szBuffer," ",MB_OK);
由于我的不解而导致模棱两可引发误导读者,请熟悉并能准确说明的高级读者多我上述的???部分进行正确说明,在此谢过了,呵呵!
========================================
2、wsprintf的用法
假设我们在.data中这样定义:
szCaptionMain db '接收消息',0
szReceive db '接收 WM_SETTEXT 消息',0dh,0ah
db '参数:%08x',0dh,0ah
db '文本: "%s"',0dh,0ah,0
Win32 API中一个很常用的函数wsprintf,这是一个字符串格式化函数,可以将数值按指定格式转换成字符串,
类似于C语言中的printf函数,它的原型是这样的:
int wsprintf(
LPTSTR lpOut, // 输出缓冲区地址
LPCTSTR lpFmt, // 格式化串地址
... // 变量列表(由此可以看出,参数个数无法确定,这正是参数入栈为什么不用stdcall 规范的原因,所有函数中的
一个特例)
);
3、作用或功能
wsprintf 与 C 语言中的功能一样都是对字符串进行格式化输出。
不过应该注意的是:wsprintf 不是将格式化结果写到标准输出,而是将其写入缓冲区中,该函数返回该字符串的长度。
三、格式化输出格式
实际使用中格式化输出以 % 打头,后跟以一个控制输出格式的字母。
1. 格式化规定符
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
符号 作用
────────────────────────────────────────
%d 格式化为十进制有符号整数输出到缓冲区
%u 格式化为十进制无符号整数输出到缓冲区
%f 格式化为浮点数输出到缓冲区
%s 格式化为字符串输出到缓冲区
%c 格式化为单个字符输出到缓冲区
%e 格式化为指数形式的浮点数输出到缓冲区
%x 格式化为无符号以十六进制表示的整数(a-f小写输出)输出到缓冲区
%X 格式化为无符号以十六进制表示的整数(a-f大写输出)输出到缓冲区
%0 格式化为无符号以八进制表示的整数输出到缓冲区
%g 格式化为自动选择合适的表示法输出到缓冲区
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
说明:
(1). 可以在"%"和字母之间插进数字表示最大场宽。
例如: %3d 表示输出3位整型数, 不够3位右对齐。
%9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。
%8s 表示输出8个字符的字符串, 不够8个字符右对齐。
如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按
实际整数位输出;若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出。
另外, 若想在输出值前加一些0, 就应在场宽项前加个0。
例如: %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。
如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。
例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。
(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。
例如: %ld 表示输出long整数
%lf 表示输出double浮点数
(3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。
例如: %-7d 表示输出7位整数左对齐
%-10s 表示输出10个字符左对齐
上面的格式化输出参照 C 语言中的 printf 函数,对于汇编语言中的 wsprintf 函数的格式化是否还有其他形式或上述格式列表中的某些项目不适用 wsprintf,我也不是很清楚。
希望大家都来参与讨论!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)