justjust001 发表于 2019-4-9 11:03:14

关于win32汇编中的wsprintf

正在学习小甲鱼老师的win32汇编,为了学习窗口消息,在消息过程中写了几段简单的程序:
捕捉WM_LBUTTONDOWN的鼠标消息,把点击的鼠标坐标显示在窗口中:
;--------变量定义
szZBText          db       'X坐标是%d,Y坐标是%d',0
szZBBuffer          db   20 dup (?)
wZB_X      dw                ?
wZB_Y      dw                ?

;--------消息过程函数处理WM_PAINT和WM_LBUTTONDOWN部分
.if        eax ==        WM_PAINT
                        invoke        BeginPaint,hWnd,addr @stPs
                        mov                @hDc,eax
                        invoke        GetClientRect,hWnd,addr @stRect
                        invoke        DrawText,@hDc,addr szZBBuffer,-1,\
                                        addr @stRect,\
                                        DT_SINGLELINE or DT_CENTER or DT_VCENTER
                        invoke        EndPaint,hWnd,addr @stPs

.elseif eax == WM_LBUTTONDOWN                               
                        mov eax,lParam
                        mov wZB_X,ax    ;lPARAM参数的低16位表示坐标X
                        mov cl,16
                        shr eax,cl         ;高16位右移至ax寄存器
                        mov wZB_Y,ax
                        invoke wsprintf,addr szZBBuffer,addr szZBText,wZB_X,wZB_Y                       
                        invoke InvalidateRect,hWnd,NULL,1

现在的问题是X坐标显示正确,Y坐标显示是一个很大的数。
但是如果我只显示一个X或者Y就是正确的:
invoke wsprintf,addr szZBBuffer,addr szZBText,wZB_X 或
invoke wsprintf,addr szZBBuffer,addr szZBText,wZB_Y

有大神能看下原因吗,个人感觉是不是wsprintf的参数设置错了?{:10_245:}

人造人 发表于 2019-4-10 12:22:48

20个字节够吗?

justjust001 发表于 2019-4-13 03:51:33

已找到原因:
和缓存区大小关系不大,就算只申请了1字节,wsprintf函数还是会把后面大得多的字符串拷贝进缓存区(所谓的内存溢出),第一个参数只是地址而已,整个函数并无长度检测机制。
考虑可能是wsprintf函数把第3个参数及以后的参数当成32位(DWORD)处理,所以重新定义wZB_X、wZB_Y为dword类型就行了。
当然后面处理的时候要用EAX给他们赋值了。
页: [1]
查看完整版本: 关于win32汇编中的wsprintf