2012-02-24 1 views
-3

나는 폼과 버튼을 사용하여 어셈블리에서 win32 프로그램을 프로그래밍하는 중입니다 ... 문제는 windows가 램의 변수를 수정하는 것입니다. 장소는 내 hInstance 및 hwnd 변수를 저장하는 곳입니다. 해결 방법을 찾았지만 우아한 해결책은 아닙니다. Windows에서 내 변수를 수정하는 이유와 응용 프로그램 시작을 설명하는 설명서를 찾을 수 있는지 알고 싶습니다.win32 매우 낮은 수준의 어셈블리 - 응용 프로그램 시작 문제

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 번째 호출에서 마지막 7 개의 변수를 수정합니다. windowsVarx를 사용하여 마지막 8 개의 변수 위치를 전환하면 windowsVarx를 수정하지 않고 hwnd, hwnd2 ...를 수정합니다. 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

Windows는 변수를 수정하지 않습니다! –

+3

어셈블리에서 프로그래밍하고 코드를 실패하게 만드는 운영 체제라고 가정하면 생산성이 떨어집니다. 디버거의 데이터 중단 점 기능을 사용하십시오. –

+1

@HansPassant, 나는 아마도 그것이 오만함보다 더 많은 무지라고 생각한다. –

답변

0

어디서부터 시작해야합니까? 코드 형식을 읽는 것은 매우 어렵습니다. 유니가 너에게 그것을 가르치 길 바란다. 어쨌든, 당신의 WindowProc은 매우 잘못되었습니다. 모든 메시지를 처리 ​​한 후에 DefWindowProc을 호출하지 마십시오. 대부분의 메시지는 eax에서 0을 반환합니다.

CreateControls를 호출 한 후 CreateControls가 끝날 때까지 4를 다시 지정하거나 4 * NumOfParamsPassed를 반환하여 esp를 추가 할 필요가 없습니다.

WindowProc이 수정되어 이제 창이 표시됩니다. 나는 또한 불필요한 많은 movs를 제거했습니다.

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!!!!! 
+0

이 코드는 고맙습니다. 정말 고맙습니다. 시스템의 실제 버그는 메시지 였고, 그것은 나의 변수 중 하나입니다. 메시지 루프의 메시지 크기가 4 바이트를 초과한다는 것을 알지 못했습니다. 그것은 실제로 윈도우가 aMsg 옆에있는 변수를 수정하고있는 것처럼 보이는 오버 플로우입니다. 고맙습니다. 모든 도움을 받으려면 지금부터 더 효율적으로 코딩 해 드리겠습니다. 내 C 배경 때문이었습니다. – andre

+0

메시지 루프의 aMsg가 MSG 구조에 대한 포인터 여야한다는 것을 알지 못했습니까? 그것은 C와 동일합니다, 그렇죠? – Gunner

+0

첫 번째 문제점을 픽업하지 않은 이유는이 절차 중에 aMsg의 첫 번째 바이트가 변경되지 않았기 때문입니다. – andre

1

문제 설명이 명확하지 않습니다. 그러나 시스템 호출을 호출하면 레지스터에 다른 값이 생길 수 있다는 것을 기억해야합니다. 나는 윈도우에 대해서는 모른다. 그러나 amd64 리눅스에서는 시스템 호출을 실행하는 커널이 레지스터의 값을 보존하기 위해서만 필요하다. r12 이상. 다른 모든 레지스터의 값은 변경 될 수 있으므로 시스템 콜에서 복귀 한 후에는 다를 수 있습니다.

이를 해결하려면 시스템을 호출하기 전에 함수 스택에 변수를 저장하십시오.

+0

앱이 시작될 때 윈도우에서 콜백됩니다. 그것을 내 스택에 저장할 때도 발생합니다. hwnd, hwnd2 만 수정합니다. 다른 변수는 수정되지 않습니다. – andre

1

Windows에서 데이터를 수정하는 것처럼 보일 수 있지만 다른 사람들이 지적했듯이 코드에서 버그 나 다른 손상이 문제를 일으킬 가능성이 큽니다.

사람들이 전체 프로그램의 런타임 동작을 미리보기 및 어셈블리 프로그래밍에서 결정한다는 것은 거의 불가능합니다. 거의 항상 고급 언어를 사용하면 거의 볼 수없는 문제가 발생합니다.

디버거를 사용하여 코드를 단계별로 실행하거나 수정되는 변수에 데이터 중단 점 을 설정하는 것이 가장 좋습니다. 데이터 중단 점은 데이터 수정을 수행하는 명령에서 프로그램을 중지하도록 설계되었습니다.

변수를 덮어 쓰는 데이터의 실제 값을 볼 수도 있습니다. 메모리를 겹쳐 쓰는 위치 또는 이유에 대한 실마리를 줄 수 있습니다.

사람들의 불쾌한 이유는 두 번째 문장에서 Windows가 프로그램이 작동하지 않는 것으로 비난한다고 가정하기 때문입니다. 많은 경우, 운영체제를 비난하는 것은 개발자가 무언가를 이해하지 못하거나 자신이 실수했다고 받아들이기를 꺼리는 좋은 신호입니다. 최종 결과는 거의 항상 실수를 지적하는 누군가입니다.

+0

디버거를 사용했으며 코드를 통해 진행 했으므로 중단 점에 대한 브리핑을 보내 주셔서 감사합니다. 정확히 어떤 호출이 내 변수를 손상시키는 지 압니다. user32.dll에 있습니다. int 2B입니다. 이것은 gcc와 링크 할 때 alink와 만 연결될 때 발생하지 않습니다. 이 코드의 목적은 Windows 32 환경에서 어셈블리를 배우는 것입니다. 내가 묻는 것은 왜 그것이 일어나는가 또는이 과정을 설명하는 일종의 문서화로서, 나는 창문을 비난하기 위해 여기에 온 것이 아니다. 당신은 창문을 비난한다고 가정합니다. 창문이 이렇게 보일 수도 있습니다. 내가 말했듯이 벌써 내 벌레를 고치는 일이있다. – andre

+0

@andre : 데이터가 손상되면 user32에서 어떤 기능을 호출합니까? – arx

+0

창문이 MyDwnProc이라면 user32로 돌아갑니다. ESI 레지스터에는 hwnd 변수의 주소 값이 들어 있습니다. 나는 결코 ESI 레지스터를 사용하지 않았다. 많은 것들이 user32에서 int 2B 호출에 도달 할 때까지 발생합니다. 이것은 27 번째 리턴 이후에 발생합니다. – andre

0

왜 CreateControls를 호출 한 후 esp에 4를 추가합니까? 스택에 1 dword를 푸시합니다. CreateControls가 스택 자체를 정리하지 않습니까? 당신은 그 기능을 썼습니까? ret 4 * 1과 같은 스택으로 조정하면 esp를 추가하면 4가 모든 것을 망칠 것입니다. 그 코드 스 니펫은 우리에게 아무런 도움이되지 않습니다. 플러스 거기에 너무 많은 unmeded movs와 jmps가 있습니다.

@David Heffernan 덕분에 저는 10 년 전에 Assembly에서 모든 프로그램을 작성하기 시작했습니다. 보존해야하고 저장할 필요가없는 경우 컴파일러가 모든 등록기를 프롤로그에 저장했기 때문에 올바른 것은 아닙니다.

+0

스택이 괜찮은지 확인했습니다. CreateControls 내 함수입니다.사용하지 않는 레지스터를 보존하는 것은 나의 의무입니까? – andre

+0

스택이 괜찮은지 어떻게 확인하고 있습니까? 우리가 확인할 수 있도록 CreateControls 함수에 대한 코드를 게시하십시오. – Gunner

+0

OllyDbg에서 확인했습니다. 스택 창에서 스택을 볼 수 있습니다. – andre