汇编中使用wsprintf函数的问题

wang13994643 2017-09-28 08:21:19
对于对汇编理解不深的我来说 有些错误真的是能把你坑的瞅谁谁不顺眼有木有。。 而且最后的错误原因就是一坨狗屎。
真的有些函数在C运行的没问题 换到汇编就不行了。 而且函数不说明 汇编只是用这个函数也不说明 到最后只能你一点点试。谁让学汇编的基数没有C多呢

请看下面这段c代码
#include <stdio.h>
#include <windows.h>

int main(){
int szBuffer[1024];

int num1=1;
char num2=2;
char s[]="第一个数是:%d,第二个数是:%d";
wsprintf(szBuffer,s,num1,num2); //wsprintf(szBuffer,s,num1,(int)num2);
这俩个都能输出1 和 2 对于这段代码有些同学可能会想 这么简单明了的几句CODE 你还有什么不懂的。 是啊这样的代码习惯性认为是正确的了 也确实正确。
printf("%s\n",szBuffer);

return 0;
} 结果输出 第一个数 1 第二个数 2

问题来了 如果换成汇编

st strcut
a db 2 dup(0)
……
st ends
或者不再结构里面定义
.data
a db 1,2
szText db '第一个数是:%d,第二个数是:%d',0
……
.code
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @hDc
local @stRect:RECT
local @szBuffer[1024]:byte
mov eax,uMsg
.if eax ==WM_PAINT
invoke wsprintf,addr @szBuffer,addr szText,a,a[1] ;这里输出的不是1和2 第一个输出正确 后面如果多余2个都不正确
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eax
invoke GetClientRect,hWnd,addr @stRect
invoke DrawText,@hDc,addr @szBuffer,-1,\
addr @stRect,\
DT_VCENTER or DT_SINGLELINE
invoke EndPaint,hWnd,addr @stPs
.elseif eax ==WM_CLOSE
call _Quit
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcWinMain endp
……

那里至今我也没弄懂到底为什么输出的不是1和2 我只知道如果把a变量类型换成dd 可以输出正确(这也是我火大找了N久才发现的原因) a dd 1,2 如果说汇编每次取4个字节 那第一个输出就应该是错的 我发现在汇编里面用wsprintf函数 如果可变参数只有1个 那不管他什么类型输出都是对的 网上一般汇编例子也只有一个可变参数。
转换类型输出连第一个也是错的 比如invoke wsprintf,addr @szBuffer,addr szText,DWORD PTR a,DWORD PTR a[1] 这里也就瞎试试 错也是意料中 感觉代码都不对
我只能找到一个办法就是每次输出前 先用一个寄存器扩展一下 比如
movzx ebx,a
movzx edx a[1]
然后invoke wsprintf,addr @szBuffer,addr szText,ebx,edx 这样输出是1和2 那问题是这样输出的是4字节 如果有特别要求 我要输出多个1字节该怎么办呢? 而且数据输出多的化 每次扩展也不是很容易 有没有其他办法???
...全文
1401 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
fhw217 2017-11-27
  • 打赏
  • 举报
回复
这是什么IDE或编辑器?
Intel0011 2017-10-29
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/392173722 有类似的问题,临时的方案也一样,DelphiGuy大神的发现也解答了我的疑惑
zara 2017-10-09
  • 打赏
  • 举报
回复
现在 masm32 里没高版本的 ml.exe 了吧,只能到 vc20.. 里找?这可要了命了
  • 打赏
  • 举报
回复
masm32v11里面的就是6.14.8444,安装免费的express或者community版本的vs就可以了。
  • 打赏
  • 举报
回复
我发现问题之所在了,应该是汇编器的问题。我用的是vs2015里带的ml.exe,14.00.24210.0,没有楼主说的问题,测试之前的版本: vs2013里的ml.exe,12.00.21005.1,没有问题 vs2010里的ml.exe,10.00.30319.01,没有问题 vc6 sp6里的ml.exe,6.15.8803,确实有楼主说的问题 masm11里带的ml.exe,6.14.8444,同样有楼主说的问题
zara 2017-10-02
  • 打赏
  • 举报
回复
这个,调试程序里看生成的最后的代码就知道了。以前遇见过类似问题,masm 在处理这个问题上有问题,和预想的 c 里的格式转换不一样,所以就不能这样操作,只能自己进行格式转换,或者就别用 masm 来对付。
wang13994643 2017-10-01
  • 打赏
  • 举报
回复
		.386
.model flat,stdcall
option casemap:none

include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib
.data?
hInstance dd ?
hWinMain dd ?
.data
a db 1,2,3
@szBuffer db 1024 dup(0)

;szTextLen dd $-szText

.const
szClassName db 'text',0
szFormat db '%d %d %d',0
szString db '%s\n',0
.code
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @hDc
local @stRect:RECT
;local @szBuffer[1024]:byte
mov eax,uMsg
.if eax ==WM_PAINT
invoke wsprintf,addr @szBuffer,addr szFormat,a,a[1],a[2]
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eax
invoke GetClientRect,hWnd,addr @stRect
invoke DrawText,@hDc,addr @szBuffer,-1,addr @stRect,\
DT_SINGLELINE OR DT_VCENTER
invoke EndPaint,hWnd,addr @stPs
.elseif eax ==WM_CLOSE
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcWinMain endp


_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSG

invoke GetModuleHandle,NULL
mov hInstance,eax
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
mov @stWndClass.lpszClassName,offset szClassName
invoke RegisterClassEx,addr @stWndClass

invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szClassName,\
WS_OVERLAPPEDWINDOW,\
100,100,650,900,\
NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain

.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax ==0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret


_WinMain endp
start:
call _WinMain
invoke ExitProcess,NULL
end start



输出不是1 2 3 输出是第一个对 1 第二个和第三个不对 131072 0 不知道到底怎么回事

  • 打赏
  • 举报
回复
随便写个测试,没有发现你说的问题:

.386p
.model flat, stdcall
option casemap: none

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

includelib d:\masm32\lib\kernel32.lib
includelib d:\masm32\lib\user32.lib

.data
a db 1, 2, 3
szFormat db '%d %d %d', 0
szString db '%s\n', 0
szBuffer db 1024 dup(0)
hHandle dd 0
nSize dd 0

.code
start:
    invoke wsprintf, offset szBuffer, offset szFormat, a, a[1], a[2]
    invoke GetStdHandle, -11
    mov hHandle,eax
    invoke WriteFile, hHandle, offset szBuffer, 1024, offset nSize, 0
    invoke ExitProcess, 0 
    ret 

    end start

21,458

社区成员

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

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