-3

我正忙着用表单和按钮在汇编中编写一个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 的回调函数。在第 27 次从 Windows 调用时,它会修改最后 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
4

4 回答 4

1

你的问题解释不是很清楚。但是您应该记住,通过调用系统调用,您可能确实会在寄存器中得到不同的值。我不了解 Windows,但在 amd64 Linux 上,内核(执行系统调用)只需要保留寄存器的值r12及以上。所有其他寄存器中的值可能会更改,因此在从系统调用返回后很可能不会相同。

为了解决这个问题,只需在调用系统之前将变量存储在函数的堆栈中。

于 2012-02-24T13:00:47.550 回答
1

Windows 似乎正在修改您的数据,但正如其他人指出的那样,您的代码中的错误或其他一些损坏更可能导致问题。

人们几乎不可能从片段中确定整个程序的运行时行为,而汇编编程几乎总是会导致使用高级语言时很少见的问题。

最好的建议是使用调试器并单步执行代码或在正在修改的变量上设置数据断点。数据断点旨在让您的程序停止执行数据修改的指令。

您还可以查看覆盖变量的数据的实际值 - 它可能会为您提供一些关于内存被覆盖的位置或原因的线索。

人们讽刺的原因是,在您的第二句话中,您假设 Windows 应该为您的程序无法正常工作负责。在许多情况下,指责操作系统是开发人员不理解某些事情或不愿意接受他们犯了错误的好兆头。最终结果几乎总是有人指出错误。

于 2012-02-24T15:25:24.287 回答
0

为什么在调用 CreateControls 后要向 esp 添加 4?您正在将 1 个 dword 推入堆栈, CreateControls 是否不清理堆栈本身?你写了那个函数?如果它确实使用 ret 4*1 之类的东西调整了堆栈,那么添加 esp, 4 会搞砸一切。那段代码对我们没有任何作用,而且那里有很多不需要的 mov 和 jmp

@David Heffernan 谢谢我 10 多年前才开始在 Assembly 中编写所有程序,并且非常清楚需要保留哪些寄存器以及需要保存哪些寄存器,因为编译器将所有寄存器保存在序言中,并不意味着它是正确的。

于 2012-02-25T18:41:28.760 回答
0

我从哪里开始?您的代码格式很难阅读。希望大学没有教你。无论如何,你的 WindowProc 是非常错误的。处理完每条消息后,不要调用 DefWindowProc,大多数消息只在 eax 中返回 0。

在调用 CreateControls 之后,您不需要添加 esp, 4,只要在 CreateControls 结束时执行 ret 4 或 ret 4 * NumOfParamsPassed。

我修复了你的 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!!!!!
于 2012-02-26T18:20:28.243 回答