我正在忙于使用表单和按钮编译程序集中的win32程序...问题是Windows在ram中修改我的变量。这个地方是我的hInstance和hwnd变量的商店。我找到了一种解决方法,但它不是一个优雅的解决方案。我想知道为什么windows会修改我的变量,也可以找到描述应用程序启动的文档。
MyWndProc:
push EBP
mov EBP, ESP
mov eax, [EBP + 12]
cmp eax, WM_DESTROY
jne MyWndProc_j2
push 0
call PostQuitMessage
jmp MyWndProc_j1
MyWndProc_j2:
cmp eax, WM_CREATE
jne MyWndProc_j1
mov eax, [EBP+8]
push eax
call CreateControls
add esp, 4
MyWndProc_j1:
mov eax, [EBP + 20]
push eax
mov eax, [EBP + 16]
push eax
mov eax, [EBP + 12]
push eax
mov eax, [EBP + 8]
push eax
call DefWindowProcA
pop EBP
ret
segment .data
Wtitle db 'My Window',0
ClassName db 'myWindowClass',0
editClass db 'EDIT',0
buttonName db 'OK',0
buttonClass db 'BUTTON',0
textName db 'My textbox',0
textClass db 'edit',0
formEdit db 'This is just a mem test', 0
windowsVar1 dd 0
windowsVar2 dd 0
windowsVar3 dd 0
windowsVar4 dd 0
windowsVar5 dd 0
windowsVar6 dd 0
windowsVar7 dd 0
windowsVar8 dd 0
aMsg dd 0
hwnd dd 0
hwnd2 dd 0
hwnd3 dd 0
hInstance dd 0
old_proc dd 0
nCmdShow dd 0
hfDefault dd 0
MyWndProc是来自windows的回调函数。在来自Windows的第27次调用时,它会修改最后7个变量。如果我用windowsVarx切换最后8个变量的位置,那么它仍然会修改hwnd,hwnd2 ...而不修改windowsVarx。其中x为1至8
CreateControls:
push EBP
mov EBP, ESP
push 0
push 0
call GetModuleHandleA
push eax
push IDC_MAIN_BUTTON
mov eax, [EBP+8] ;hwnd
push eax
push 24
push 100
push 220
push 50
mov eax, WS_CHILD
or eax, BS_DEFPUSHBUTTON
or eax, WS_TABSTOP
or eax, WS_VISIBLE
push eax
push buttonName
push buttonClass
push 0
call CreateWindowExA
mov [hwnd2], eax
push DEFAULT_GUI_FONT
call GetStockObject
mov [hfDefault], eax
push 0
mov eax, [hfDefault]
push eax
push WM_SETFONT
mov eax, [hwnd2]
push eax
call SendMessageA
push 0
push 0
call GetModuleHandleA
push eax
push IDC_MAIN_EDIT
mov eax, [EBP+8] ;hwnd
push eax
push 100
push 200
push 100
push 50
mov eax, WS_CHILD
or eax, ES_MULTILINE
or eax, ES_AUTOVSCROLL
or eax, ES_AUTOHSCROLL
or eax, WS_VISIBLE
push eax
push 0
push editClass
push WS_EX_CLIENTEDGE
call CreateWindowExA
mov [hwnd3], eax
push 0
mov eax, [hfDefault]
push eax
push WM_SETFONT
mov eax, [hwnd3]
push eax
call SendMessageA
push Wtitle
push 0
push WM_SETTEXT
mov eax, [hwnd3]
push eax
call SendMessageA
pop EBP
ret
以下函数是消息循环,它收集和发送。
MyMessageLoop:
push 0
push 0
push 0
push aMsg
call GetMessageA
cmp eax, 0
je MyMessageLoop_j1
push aMsg
call TranslateMessage
push aMsg
call DispatchMessageA
jmp MyMessageLoop
MyMessageLoop_j1:
ret
答案 0 :(得分:1)
你的问题解释不是很清楚。但是你应该记住,通过调用系统调用,你的寄存器中可能确实会有不同的值。我不了解Windows,但是在amd64 Linux上,内核(执行系统调用)只需要保留寄存器r12
及以上的值。所有其他寄存器中的值可能会更改,因此从系统调用返回后很可能不会相同。
为了解决这个问题,只需在调用系统之前将变量存储在函数的堆栈中即可。
答案 1 :(得分:1)
Windows似乎正在修改您的数据,但正如其他人所指出的那样,代码中的错误或其他一些损坏更可能导致问题。
人们几乎不可能从片段中确定整个程序的运行时行为,而汇编中的编程几乎总是会导致在使用高级语言时很少出现的问题。
最好的建议是使用调试器并逐步执行代码或对要修改的变量设置数据断点。数据断点旨在使程序停止执行数据修改的指令。
您还可以查看覆盖变量的数据的实际值 - 它可能会为您提供有关内存被覆盖的位置或原因的一些线索。
人们讽刺的原因是,在你的第二句话中,你认为Windows应该归咎于你的程序不起作用。在许多情况下,指责操作系统是开发人员不理解某些内容或不愿意接受他们犯了错误的好兆头。最终结果几乎总是别人指出错误。
答案 2 :(得分:0)
为什么在调用CreateControls后向esp添加4?你正在将1个dword推入堆栈,CreateControls不会清理堆栈本身吗?你写了那个功能?如果它确实用ret 4 * 1之类的东西调整堆栈然后添加esp,那么4就是搞砸了所有东西。那段代码对我们没有任何帮助,而且那里有很多不受欢迎的mov和jmps
@David Heffernan谢谢我刚刚开始在大会上编写我的所有程序,并且很清楚需要保存的寄存器以及何时不需要保存它们,只是因为编译器会保存所有寄存器序言,并不代表它是正确的。
答案 3 :(得分:0)
我从哪里开始?您的代码格式很难阅读。希望Uni不会教你。无论如何,你的WindowProc非常错误。在您处理的每条消息之后,您不要调用DefWindowProc,大多数消息只是在eax中返回0。
在调用CreateControls之后,只要在CreateControls结束时再执行4或者返回4 * NumOfParamsPassed,就不需要添加esp,4。
我修复了你的WindowProc,现在显示了窗口。我还删除了许多不需要的mov。
MyWndProc:
push ebp
mov ebp, esp
mov eax, dword ptr[ebp + 3 * 4] ; same as [ebp + 12]
cmp eax, WM_CREATE
je _CREATE
cmp eax, WM_CLOSE
je _CLOSE
PassThrough:
push dword ptr[ebp + 5 * 4]; same as [ebp + 20]
push dword ptr[ebp + 4 * 4]; same as [ebp + 16]
push dword ptr[ebp + 3 * 4]; same as [ebp + 12]
push dword ptr[ebp + 2 * 4]; same as [ebp + 8]
call DefWindowProc
jmp _DONE
_CLOSE:
push 0
call PostQuitMessage
jmp _RET0
_CREATE:
push dword ptr[ebp + 2 * 4]
call CreateControls
;add esp, 4
_RET0:
xor eax, eax
_DONE:
pop ebp
ret 4 * 4 ; <----- you were missing this!!!!!