高手帮忙啊wsprintf的问题

otmac 2008-10-08 11:38:37
小弟初学WIN32汇编,遇到这个问题实在想不明白。写了个小程序目的是弹出对话框显示当前时间。但显示的时间只有hour是正确的,minute是一个7位数,而second总是0(-_-),我在调试的时候发现GetLocalTime后时间都是正确的,但是调用wsprintf放在一个缓冲区后,就出错了(-_-)。还有,看资料说WIN32的API中只有wsprintf的调用方式是C,于是我就加了一行add esp, 10,但是我看《WINDOWS环境下的32位汇编》那本书第10章的例子用了wsprintf之后都没有add esp啊,而且没有出问题。我的程序中不加add esp弹出的对话框不会显示标题,不会显示缓冲区的内容(就是时:分:秒,即使是错误的),甚至连确定按钮上的”OK"都没有显示(-_-),是什么原因呢?
代码如下:
.386
.model flat, stdcall
option casemap: none

include d:\masm32\include\windows.inc
include d:\masm32\include\user32.inc
include d:\masm32\include\kernel32.inc
includelib d:\masm32\lib\user32.lib
includelib d:\masm32\lib\kernel32.lib

.const
szFormat db '%d:%d:%d', 0
szTitle db 'ShowTime', 0

.data
szSysTime db 10 dup(0)
stSysTime SYSTEMTIME <>

.code

start:
invoke RtlZeroMemory, addr stSysTime, sizeof SYSTEMTIME
invoke GetLocalTime, addr stSysTime
invoke wsprintf, addr szSysTime, addr szFormat, \
stSysTime.wHour, \
stSysTime.wMinute, \
stSysTime.wSecond

add esp, 10 ;5*dword?
invoke MessageBox, NULL, addr szSysTime, addr szTitle, MB_OK
invoke ExitProcess, NULL

end start
...全文
256 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
sysadm_cc 2008-11-03
  • 打赏
  • 举报
回复
时间函数返回的那个结构中各成员需要扩展到32位再入栈。请参考《Windows环境下32位汇编语言程序设计》第一版198页关于GetLocalTime返回的数据结构SYSTEMTIME中各成员的数据类型的使用。
sysadm_cc 2008-11-03
  • 打赏
  • 举报
回复
获取系统时间的函数得到的时间的数据类型和输出的时候制定的%d不符吧,还有不管是什么调用方式你不需要自己平衡堆栈,那是编译器的事,你那条指令是多余的
otmac 2008-10-11
  • 打赏
  • 举报
回复
那要怎么修改才正确呢?
otmac 2008-10-11
  • 打赏
  • 举报
回复
我觉得问题也只有在那里了,但是汇编中好像不能使用sprintf啊?我用的时候编译出错:undefined symbol : sprintf,然后才用的wsprintf
疯哥哥 2008-10-11
  • 打赏
  • 举报
回复
哦?
但是我还是不明白为什么它会按word入栈呢。。
要是直接
push stSysTime.wSecond
push stSysTime.wMinute
push stSysTime.wHour
push offset szFormat
push offset szSysTime
call wsprintf
add esp,XXOO
这样不对么?
如果这样对的话,就是按dword入栈了啊。。。
难道是invoke的问题吗。。。。要指定align 8?
不明白啊。。
靠,我自己去试试去。
笨鸟无敌 2008-10-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zoologist 的回复:]
我的意思是 wsprintf 按照dword压入的,而stSysTime.wHour是word,这就是问题所在,

所以要处理一下。

汇编有CTXT()可以用~
[/Quote]
嗯,指出了问题的关键所在.

针对这个程序清样,程序楼上办法可行呵.
otmac 2008-10-11
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 mydo 的回复:]
不想浪费寄存器:


Assembly code
movzx eax,stSysTime.wSecond
push eax
movzx eax,stSysTime.wMinute
push eax
movzx eax,stSysTime.wHour
push eax
push offset szFormat
push offset szSysTime
call wsprintf




你可以看看一些c编译器的类似实现,大致如上。
[/Quote]
再次感谢mydo大虾。
大熊猫侯佩 2008-10-11
  • 打赏
  • 举报
回复
不想浪费寄存器:


movzx eax,stSysTime.wSecond
push eax
movzx eax,stSysTime.wMinute
push eax
movzx eax,stSysTime.wHour
push eax
push offset szFormat
push offset szSysTime
call wsprintf


你可以看看一些c编译器的类似实现,大致如上。
otmac 2008-10-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 mydo 的回复:]
一种笨方法:


Assembly code
.code

start:
invoke RtlZeroMemory, addr stSysTime, sizeof SYSTEMTIME
invoke GetLocalTime, addr stSysTime

movzx eax,stSysTime.wHour
movzx ebx,stSysTime.wMinute
movzx ecx,stSysTime.wSecond

invoke wsprintf, addr szSysTime, addr szFormat,eax,ebx,ecx

;add esp, 10 ;5*dword?
invoke MessageBox, NULL, addr szSysTime, addr szTitle, MB_OK
invoke ExitProces…
[/Quote]
谢谢mydo,扩展后确实可以解决问题,但是如果参数多了的话比寄存器不够用,就不太现实了啊。
还有没有什么办法可以解决word和dword的问题呢?zoologist 大侠提到的CTXT,我在调用invoke时直接用了CTXT("%d:%d:%d"),但是提示CTXT没定义,是要包含macros.inc吗?我找了一下,找不到macros.inc这个文件啊.
还有就是关于恢复堆栈的问题,C调用方式说的是要调用者自己恢复堆栈,用invoke不需要恢复,如果用call就需要手动恢复了是吧?我调试的时候发现invoke后面确实有了add esp,但不是我写的,应该是编译器自己处理的吧?
大熊猫侯佩 2008-10-11
  • 打赏
  • 举报
回复
一种笨方法:


.code

start:
invoke RtlZeroMemory, addr stSysTime, sizeof SYSTEMTIME
invoke GetLocalTime, addr stSysTime

movzx eax,stSysTime.wHour
movzx ebx,stSysTime.wMinute
movzx ecx,stSysTime.wSecond

invoke wsprintf, addr szSysTime, addr szFormat,eax,ebx,ecx

;add esp, 10 ;5*dword?
invoke MessageBox, NULL, addr szSysTime, addr szTitle, MB_OK
invoke ExitProcess, NULL

end start
疯哥哥 2008-10-10
  • 打赏
  • 举报
回复
不知道汇编里面有没有像_T()
或者TEXT()这样的宏...
zoologist 2008-10-10
  • 打赏
  • 举报
回复
invoke wsprintf, addr szSysTime, addr szFormat, \
stSysTime.wHour, \
stSysTime.wMinute, \
stSysTime.wSecond 《-------这个地方压栈的问题


可以参考:
http://www.aogosoft.com/downpage.asp?mode=viewtext&id=199
疯哥哥 2008-10-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 jesterjy 的回复:]
wsprintf是C的调用方式,但是也不需要你自己清栈.
调用方式说的是函数的调用和被调用关系,这些好象都只是编译器自己解决.
[/Quote]
嗯,invoke这个宏应该会解决这个问题的.
如果单纯使用汇编的call指令,那么c调用的参数必须手动平衡堆栈.
疯哥哥 2008-10-10
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zoologist 的回复:]
我的意思是 wsprintf 按照dword压入的,而stSysTime.wHour是word,这就是问题所在,

所以要处理一下。

汇编有CTXT()可以用~
[/Quote]
哦,word入栈?
32位下程序不是按dword入栈的吗~~~~栈对齐啊.硬件级支持的啊(IA32).
比如void foo(char bar),这个bar是dword对齐的吧.
疯哥哥 2008-10-10
  • 打赏
  • 举报
回复
wsprintf到底是stdcall还是cedcl,你可以自己试试,加了add esp和不加,肯定不一样的...我可以99%的肯定,它是c调用.因为只有c调用才支持变参.
wsprintf是宽字符的打印,你可以换成sprintf
或者将
szFormat db '%d:%d:%d', 0
改成
szFormat dw '%d:%d:%d', 0 这种该法不一定对,因为我没整过win32汇编~~但问题就出在这儿.
过去的我 2008-10-10
  • 打赏
  • 举报
回复
zoologist 好像就是汇编通讯的主编~
zoologist 2008-10-10
  • 打赏
  • 举报
回复
我的意思是 wsprintf 按照dword压入的,而stSysTime.wHour是word,这就是问题所在,

所以要处理一下。

汇编有CTXT()可以用~
jesterjy 2008-10-10
  • 打赏
  • 举报
回复
wsprintf是C的调用方式,但是也不需要你自己清栈.
调用方式说的是函数的调用和被调用关系,这些好象都只是编译器自己解决.

21,500

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧