News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

I am new and Can anybody explain some part of the TD's code

Started by chiqui.paula, May 11, 2015, 04:35:48 PM

Previous topic - Next topic

chiqui.paula

Hello everybody. I am happy to be here. I have been examining the code below but I dont understand the definition under ' .const " part and the part that under the "WP1:" label.
1) What is the purpose of defining .const part in the way that it is done?
2) Why do we set stack frame?
3) Why do we use "pushad" after creating the stack frame? (why not before?)
4) Where did we get a valid value inside the  "WP1_uMsg" so that we use the command "mov     eax,WP1_uMsg".

I gave the whole code is attached in txt file. Thanks in advance for your kind answers to my questions.


Thanks,

Paula Chiqui,

rrr314159

Hello Paula,

the .const's are being used to address the parameters in the stack frame. So, [ebp+8] will access the first one, for instance. (ebp+4 is the return address, ebp+0 points at where we stored ebp when we created the frame.) They're constants because you never want them to change during the life of the program ...

However there is something odd / wrong with this code; who wrote it? The ".const" statement is useless. WP1_uMsg is actually a symbolic equate; later on the "[ebp+12]" will simply be substituted, literally, for it. .const should be used to define a data value which won't change - that's not being done here. Strange.

I notice just above, where the const statement is explained, it says "0Ah = the value in hexadezimal". Apart from the spelling mistake it doesn't accurately reflect the actual statements. Sombody hacked this code I think - some junior teaching assistant? In fact this is the reason I'm answering despite suspecting this is homework - I can't blame you for being confused.

Now, the stack frame is just a normal stack frame, you must have read an explanation what it's for. What didn't you understand about it? There are five DWORDs above the entry point to the WP1 function. You put that entering address into ebp so u can access them later (well, not the return address; the other 4). Now you can use the stack - which changes the value of esp - but ebp remains the same, so u can still get at the entering parameters.

If u did "pushad" before saving ebp, that scheme wouldn't work, because pushad modifies esp by saving registers on the stack. Whole idea is to save the entering esp value before playing with the stack.

For the command "mov eax,WP1_uMsg" the assembler, before doing anything else, substitutes the symbolic constant's text value u defined above for WP1_uMsg, so the statement becomes

mov eax, [ebp+12]

then when it gets compiled / executed this puts the 3rd DWORD above ebp (because 4*3 = 12, 4 is the size of a DWORD, and ebp+0 is where ebp itself is stored) into eax.

Now I would like to point out that if this is homework I'm doing for you, you are doomed to fail in life because you need to learn to do your own work and not rely on helpful strangers. Best to learn it now not when begging in the gutter for a handout; I won't be so generous then! U can redeem yourself by making sure you understand the explanation thoroughly; then it's almost as though it is your own work. If it's NOT homework pls ignore the above.

Have a nice day!
I am NaN ;)

chiqui.paula

rrr314159,

Thank you for your kind response. The code belongs to Test Department. So the code is neither for school (HW, project etc) nor for my job. I am just trying to learn from tutorials and asking the part of the code that I dont understand.

Maybe that's the reason (probably most people think that this is for HW) nobody answered my questions but you :)

The reasons that I am confused.

1) The reason I have been confused is that we nail the "WP1_Callback" return address and its parameters (which acts as WndProc), but in the "WP1:" first we set the stack frame and then use "pushad" which modifies the stack (as you said), but the parameters that we set under ".const" will not belong to where they are supposed to because there will be now the other registers due to "pushad" command.

2) Any part of the code above the label "WP1:", we dont ever assign any value into "WP1_uMsg" which equals to "[ebp+12]" until "pushad" command which will put some registers in there as well. So I am guessing thie part of my confusion comes from the first part as well.

3) Where exactly (specifically which line) we get the value put into "WP1_uMsg" so that at the very bottom of the code we call "DefWindowProcA" funtion?


Thanks,

PC

dedndave

this is some really old code - lol
it starts off with .386
i suggest .486 or higher because it allows modern addressing modes, etc

another problem i see is "include D:\Masm32\include\windows.inc"
the masm32 package was designed for root-relative paths, on the current drive
it should be "include \Masm32\include\windows.inc" (no drive specifier)

also, there are several PROTOtypes defined that are defined for you if you add the proper includes
functions like GetModuleHandleA specify the ANSI version (as opposed to the UNICODE version)
just use GetModuleHandle
the masm32 package is set up to use the appropriate version, according to whether or not the symbol __UNICODE__ is defined
if __UNICODE__ is defined, it will use GetModuleHandleW
if it is not defined, it will use GetModuleHandleA

typically, we might start the program with "include \masm32\include\masm32rt.inc"
that single line takes care of the processor, model, casemap, and adds the most often used includes and libraries

it is not necessary to open a .CONST section to define EQUates
that is a common misconception
EQUates are essentially assembly-time symbols that have a constant value
the .CONST section would be opened to define run-time data that may not be altered
in other words, the .CONST section is similar to the .DATA section, except it is read-only

stack frames allow a fast, efficient way to allocate temporary memory buffers
the life of the buffer is the life of the PROC
stack frames also allow consistent access to passed arguments

personally, i never use PUSHAD
well - there are special cases where i want all the register contents available
for example, if i were writing a DumpRegs routine, i might use PUSHAD

as to why it is added after the stack frame is created, instead of before - good question - lol
i don't know why anyone would set up a stack frame that way
if you search the forum, you will see that i have posted many examples of stack frames
with registers preserved before the stack frame is created

WP1_uMsg is a passed argument
when the operating system calls WndProc, it passes 4 arguments:
hWnd, uMsg, wParam, lParam

the way this code is written is very poor - and out of date
i would not suggest you use it as an example of how to write win32 asm code
in the masm32\examples folder, you will find many better examples of WndProc code

finally, a link to the MSDN page for WndProc
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573%28v=vs.85%29.aspx

a simple WndProc ASM example...
WndProc PROC    hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    mov     eax,uMsg
    .if eax==WM_CREATE
        mov     edx,hWnd
        mov     hwndMain,edx
        xor     eax,eax

    .elseif eax==WM_CLOSE
        INVOKE  DestroyWindow,hWnd
        xor     eax,eax

    .elseif eax==WM_DESTROY
        INVOKE  PostQuitMessage,NULL
        xor     eax,eax

    .else
        INVOKE  DefWindowProc,hWnd,uMsg,wParam,lParam

    .endif
    ret

WndProc ENDP

chiqui.paula

dedndave,

Thank you for your detailed explanations and suggestions and also I am glad that I am not the only one thinks that the code is little bit odd especially on creating the stack frame part and the ".const" part.

One final question and please forgive me being so insistent. Is there any way to write "WndProc" by not using the "proc" and "invoke"? and why did you clean your "eax" register after every case in your "WndProc" (because to be able to use eax register for obtaining the future returning values )?

Thank you,

PC,




dedndave

the masm assembler will generate a prologue and epilogue for you, if you want it to
in other words, it takes care of setting up and releasing the stack frame
all you have to do is not use the EBP register

if you read the documentation for WndProc, you will see that the operating examines the return value (EAX)
at least, this is true for most messages, i think
for messages passed to DefWindowProc, that function takes care of the return value

i prefer to write the code, as shown, so that each message may return different values
other forum members return 0 for all messages that aren't passed to DefWindowProc
to know what value to return, look at the documentation for each specific message

here are a couple examples...

https://msdn.microsoft.com/en-us/library/windows/desktop/ms632646%28v=vs.85%29.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/bb787524%28v=vs.85%29.aspx

dedndave

you can also write your own stack frame, if desired
search the forum for code that uses OPTION to set the prologue and epilogue
i have posted several examples, including some with complex stack frames

dedndave


dedndave


dedndave

i guess i forgot to answer that one question....

you can write a procedure without using PROC, but why would you want to ?
it makes the code very hard to write and to modify

SomeFunc: mov eax,5
    ret

...

    call    SomeFunc


yuck   :P

chiqui.paula

dedndave,
Thanks for your replies :)

But one thing that still bothers me and I still dont understand in the code I have attached is how we assign a value inside to "WP1_uMsg"? Since that is not used nowhere in the code before "WP1:" label, how does Masm knows that there is a legit value inside "WP1_uMsg" but not a random value? I thought that it was the "DispatchMessage" function that puts a returning value inside "WP1_uMsg", but I dont think so.

Any idea?

dedndave

it's an EQUate - actually, it's a TEXTEQUate

WP1_uMsg                equ [ebp+12]

whenever the assembler sees "WP1_uMsg", it replaces it with "[ebp+12]"

jj2007

To understand what's going on, place an int 3 directly after WP1 and watch in Olly what happens:

mov     lpfnWndProc,OFFSET WP1          ;address of user lpfnWndProc function
(#### here you tell Windows where your application's message loop starts)
...

WP1:
int 3
push    ebp                             ;create stack frame
mov     ebp,esp                         ;
pushad                                  ;push all register to the stack

mov     eax,WP1_uMsg           ; [ebp+12] move the message number in eax
(#### Windows places the message on the stack, it ends up in [ebp+12])

dedndave

there are times when i might write a function without using PROC
for example, i have a "helper" function, inside a regular function
the Helper function avoids repetition of the same code, and
i want the helper function to have access to the same stack frame as the original procedure...

SomeFunc PROC  dwArg:DWORD

    LOCAL   dwLocal :DWORD

;some code here

    call    Helper

;some more code

    call    Helper

;some more code

    ret                    ;end of main function

;------------------

Helper:

;some code here - the Helper function has access to dwArg and dwLocal

    retn               ;specifies a NEAR return, with no epilogue

SomeFunc ENDP

jj2007

Quote from: dedndave on May 12, 2015, 04:02:53 AMi want the helper function to have access to the same stack frame as the original procedure...

More precisely, to the same args and local variables. I use that quite a lot.

Have a look at reply #12 and the parts marked with ####.