flat assembler
Message board for the users of flat assembler.
Index
> Windows > Win32 programming without includes Goto page Previous 1, 2 |
Author |
|
Pinecone_ 05 Oct 2008, 08:08
When the CPU gets to a call instruction, it has two jobs to do: push the address of the next function onto the stack, so it knows where to return to with ret instruction, and jump to the address specified.
When your procedure gets called, if you are expecting to use arguments and the stack within your procedure, you should push ebp onto the stack and mov the value of esp into ebp so you can reference to the arguments passed to your procedure. The leave command pops ebp back off the stack, and ret jumps back to the next instruction after the call which called your procedure. The whole process may be explained a little better like this: Code: call Test ; push address of next instruction onto stack and jump to test procedure Code: Test: push ebp mov ebp, esp ; ... do whatever here, use the stack as normal and use ebp to reference the arguments passed to Test ; say you wanted to get the value passed in argument number two into eax: ; mov eax, [ebp + C] ; it's ebp + c because ebp + 0 is the origonal value of ebp ; ebp + 4 is the address to return to with ret instruction ; from ebp + 8 is your arguments leave ; basically restores ebp - i think equal to Mov Ebp, [Ebp] and Add Esp, 4 ret NUMBER_OF_ARGS*4; pop arguments off the stack, return back to instruction after call I'm probably not the best person at explaining that, please someone correct me if i got something wrong... good luck with fasm pal. Edit: sorry for bumping old topic - i forgot to look at the dates Last edited by Pinecone_ on 17 Oct 2008, 13:44; edited 1 time in total |
|||
05 Oct 2008, 08:08 |
|
pal 12 Oct 2008, 21:36
Ahh cheers mate, that actually helped a lot. I understand better now. I knew that it pushed the return address value to the stack, but didn't know much about the leave command. Cheers mate.
|
|||
12 Oct 2008, 21:36 |
|
bitshifter 17 Oct 2008, 07:04
One thing i noticed is that you are using DefWindowProc in a dialog procedure.
A WindowProc should be used to compliment RegisterClass and CreateWindow. A DialogProc should be in any other case. (IE: DialogBox, DialogBoxParam) A WindowProc should call DefWindowProc for default processing of unhandled messages. A DialogProc should simply return zero for default processing of unhandled messages. Also, because both are CALLBACK type functions, we should preserve ebx,esi,edi. Code: ;------------------------------------------------ ; hwnd: dword[ebp+8] ; umsg: dword[ebp+12] ; wparam: dword[ebp+16] ; lparam: dword[ebp+20] ;------------------------------------------------ Code: WindowProc: push ebp mov ebp,esp push ebx esi edi cmp dword[ebp+12],0x0010 je .wmclose cmp dword[ebp+12],0x0002 je .wmdestroy cmp dword[ebp+12],0x0001 je .wmcreate .defwndproc: push dword[ebp+20] push dword[ebp+16] push dword[ebp+12] push dword[ebp+8] call [DefWindowProc] jmp .finish .wmcreate: mov eax,1 jmp .finish .wmclose: push dword[ebp+8] call [DestroyWindow] xor eax,eax jmp .finish .wmdestroy: push 0 call [PostQuitMessage] xor eax,eax .finish: pop edi esi ebx mov esp,ebp pop ebp ret 16 Code: DialogProc: push ebp mov ebp,esp push ebx esi edi cmp dword[ebp+12],0x0010 je .wmclose cmp dword[ebp+12],0x0110 je .wminitdialog: .defdlgproc: xor eax,eax jmp .finish .wminitdialog: mov eax,1 jmp .finish .wmclose: push 0 push dword[ebp+8] call [EndDialog] mov eax,1 .finish: pop edi esi ebx mov esp,ebp pop ebp ret 16 Last edited by bitshifter on 24 Oct 2008, 02:02; edited 1 time in total |
|||
17 Oct 2008, 07:04 |
|
asmcoder 17 Oct 2008, 11:12
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:55; edited 1 time in total |
|||
17 Oct 2008, 11:12 |
|
Pinecone_ 17 Oct 2008, 13:10
no idea about enter, but leave does restores ebp. i haven't looked it up in a manual or anything (i should get around to it someday) so i don't know specifics, but if you step through a procedure generated by the proc/endp macros, look at what registers are changed by the leave instruction, ebp and esp. i guessed what i wrote in my above post from my observations of it so i could be off about some of that... but generally i think it's pretty much right
edit: i forgot to mention, i figure leave is equal to something like: mov ebp, [ebp] add esp, 4 also added that in the comments in above post Last edited by Pinecone_ on 17 Oct 2008, 13:52; edited 1 time in total |
|||
17 Oct 2008, 13:10 |
|
revolution 17 Oct 2008, 13:15
I think it would be faster to RTFM than to post a question here.
C'mon people, the manuals are you saviour, don't go coding things based upon myths and guesses. |
|||
17 Oct 2008, 13:15 |
|
Pinecone_ 17 Oct 2008, 13:50
No myths, and they were educated guesses after analysis. It would've been easier to read the manual, but the question was asked, so i answered.I found out my own way because back when i was trying to figure this stuff out, i didn't have a copy of Intel architecture instruction set manual 'cause i was just starting after that, i have never had a need to look it up in the manual
|
|||
17 Oct 2008, 13:50 |
|
bitRAKE 17 Oct 2008, 14:37
ENTER can be used to copy an array at (E|R)BP to the stack - very handy four byte instruction. It was designed to support multi-level call stacks and back-tracking; but it is good to also understand it at a low level.
Here is my attempt to consolidate the manual: Code: ENTER FRAME,NEST { push (r|e)bp ; BP, EBP, RBP mov [frametemp],(r|e)sp ; SP, ESP, RSP if NEST<>0 while NEST>1 sub (r|e)bp,SIZEOF ; 2, 4, 8 push SIZE [(r|e)bp] ; word,dword,qword dec NEST end while push SIZE [frametemp] ; word,dword,qword end if mov (r|e)bp,[frametemp] ; BP, EBP, RBP sub (r|e)sp,FRAME ; SP, ESP, RSP } The while loop copies an array from (R|E)BP! (moving backwards in address values ) 99.99% of all ENTER use has NEST=0! _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
17 Oct 2008, 14:37 |
|
LocoDelAssembly 17 Oct 2008, 14:52
Quote:
In fact Code: mov esp, ebp
pop ebp |
|||
17 Oct 2008, 14:52 |
|
asmcoder 17 Oct 2008, 17:11
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:55; edited 1 time in total |
|||
17 Oct 2008, 17:11 |
|
LocoDelAssembly 17 Oct 2008, 21:31
Yes, why do you use it that way? EBP is used as a fixed pointer to access local variables and parameters, not to hold the base address of the local variables. In the positive offsets you have the parameters and in the negative ones the local variables. By doing it in your way you are confusing the debugger that relies on having at [EBP] the old EBP and if the local variables are big enough (like your example), the offset for accessing the parameters won't be encoded as signed imm8 but in full imm32 instead, making the instructions that access parameters larger.
|
|||
17 Oct 2008, 21:31 |
|
Pinecone_ 18 Oct 2008, 01:14
ahh so i was wrong that makes much more sense when i think about it Thanks
|
|||
18 Oct 2008, 01:14 |
|
asmcoder 18 Oct 2008, 13:22
[content deleted]
Last edited by asmcoder on 14 Aug 2009, 14:55; edited 1 time in total |
|||
18 Oct 2008, 13:22 |
|
LocoDelAssembly 18 Oct 2008, 15:45
It is still wrong You must move ESP to EBP before any modification to ESP (besides "push ebp") takes place.
Code: ;proc foo a, b, c ;local buff:BYTE[666], alfa:DWORD push ebp mov ebp, esp sub esp, 4+666 mov eax, [ebp+8] ; mov eax, [a] add eax, [ebp+16] ; add eax, [c] lea edx, [ebp-4-666] ; lea edx, [buff] ; char *edx = &buff[0] mov ecx, [ebp-4] ; mov ebp, [alfa] leave ; mov esp, ebp / pop ebp ret ;endp This way, no matter how many times you alter ESP with push, pop, or whatever, EBP will be at a fixed position so your offsets can be constant. You are not obligated to make your procedures EBP-based though, but then, debuggers won't be able to build up the stack trace unless debugging information is present. As another advantage you have the code size, the code above takes 26 bytes but the ESP-based one takes 37. I have tried to found references but I failed so I have to ask: does the ESP-based frame generates AGI stalls on some processors? (non leaf functions of course) |
|||
18 Oct 2008, 15:45 |
|
asmcoder 18 Oct 2008, 17:51
[content deleted]
|
|||
18 Oct 2008, 17:51 |
|
Goto page Previous 1, 2 < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.