The MASM Forum

General => The Campus => Topic started by: Abdel Hamid on January 25, 2019, 08:11:28 AM

Title: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 08:11:28 AM
Hello friends ,
i've been trying to understand this piece of code from tutorial N°5 of iczelion series

LOCAL hdc:HDC
    LOCAL ps:PAINTSTRUCT
    LOCAL hfont:HFONT ////////////////////////
    .IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL
    .ELSEIF uMsg==WM_PAINT
         invoke BeginPaint,hWnd, ADDR ps 
        mov    hdc,eax
        invoke CreateFont,50,25,0,0,200,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,0\
        ,PROOF_QUALITY,DEFAULT_PITCH or FF_DONTCARE,addr FontName
        invoke SelectObject, hdc, eax
        mov    hfont,eax //////////////////////////////////
        RGB    200,200,50
        invoke SetTextColor,hdc,eax
        RGB    0,0,255
        invoke SetBkColor,hdc,eax
        invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString
        invoke SelectObject,hdc, hfont ; //////////////////////// (eax instead of hfont)
        invoke EndPaint,hWnd, ADDR ps
       .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF

maybe it's a silly question but i  couldn't figure out why iczelion used the local variable hfont ?
i mean we can have the same result without using it ...
createobject returns a handle to the object (being replaced ) ? (i've read about it in the Win32api help file but i still don't understand how it works !
someone help me , i can't move to the next tutorial without understanding this point  :icon_rolleyes:
thank you in advance  :t
Title: Re: Fifth tutorial of iczelion series
Post by: AK_AK on January 25, 2019, 08:37:10 AM
Im not an expert, but im not brand new either, ill suggest the following:

i believe this is because EAX, being a register is volatile, and may also have a relative reference at times.
it is stable code that places a register value in a local var instead of relying on a volatile register to stay untouched for the duration of the code operations.
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 08:43:23 AM
Quote from: AK_AK on January 25, 2019, 08:37:10 AM
Im not an expert, but im not brand new either, ill suggest the following:

i believe this is because EAX, being a register is volatile, and may also have a relative reference at times.
it is stable code that places a register value in a local var instead of relying on a volatile register to stay untouched for the duration of the code operations.
Hello friend , thanks for your post
it could be right , but he could just move "eax" to "ebx" simply !, "ebx" in not volatile register  :icon_confused:
Title: Re: Fifth tutorial of iczelion series
Post by: TBRANSO1 on January 25, 2019, 08:55:23 AM
I was going to give the same type of answer.

I would replace the eax with the hFont in the code.  I think it's better to get into the habit of using the local stack to store variables, so at least you don't have to think about whether which registers are going to be used by Windows.  I read by Mr. Hutch that Windows during subsequent calls doesn't care about your stinking registers and will doing what it wants with them, so at least store them locally and don't worry about it.
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 09:06:13 AM
Quote from: TBRANSO1 on January 25, 2019, 08:55:23 AM
I was going to give the same type of answer.

I would replace the eax with the hFont in the code.  I think it's better to get into the habit of using the local stack to store variables, so at least you don't have to think about whether which registers are going to be used by Windows.  I read by Mr. Hutch that Windows during subsequent calls doesn't care about your stinking registers and will doing what it wants with them, so at least store them locally and don't worry about it.
Hello friend ,
i thought it's cool to use registers , now i'll try to use local var instead  :biggrin:
thank you for the info  ;)
Title: Re: Fifth tutorial of iczelion series
Post by: jj2007 on January 25, 2019, 09:25:20 AM
Read The "register gets trashed" trap here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm).
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 09:36:32 AM
Quote from: jj2007 on January 25, 2019, 09:25:20 AM
Read The "register gets trashed" trap here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm).
thank you sir for the amazing content that you posted there , i tried to read it yesterday but i fall asleep i was so tired  :bgrin:
i'll read it carefully ...
note : you've mentioned that " The following is addressed to those who have experience in a high level language such as BASIC or C."
am not experienced in any other high level language , but i can understand every single word  :biggrin:
Regards 

Title: Re: Fifth tutorial of iczelion series
Post by: AK_AK on January 25, 2019, 09:58:49 AM
one of the things that you will see in windows code, and any other code that switches machine context, is storage of the machine state on stack before the call to your ASM function.  you will see the registers, and any other thing that you want to restore when you exit from loop   [the current stack pointer value] , PUSHED into the stack, the function is then called , executed, exited then the stack pointer is set to your stack frame position and the registers are restored by popping the register values, from stack into registers, and windows [or whatever OS is in place} is now back where it was before you called your function. and you may now RET from your function back to the OS previous position in the code.

This is done because, as mentioned earlier, Windows does all sorts of things to the registers, even non volatile ones. 
you may find a partial discussion of this in the REGISTER TRASH TRAP that is indicated in this thread.

http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 10:48:18 AM
Quote from: AK_AK on January 25, 2019, 09:58:49 AM
Windows does all sorts of things to the registers, even non volatile ones. 
ebx , esp , ebp are protected registers even in subroutines
unless you wanted to use them then restore their values at the end !
so how can windows change their values ?
jj2007 has given me the link that you provided  :t
Title: Re: Fifth tutorial of iczelion series
Post by: AK_AK on January 25, 2019, 10:58:02 AM
the windows kernel operates in a place called ring 0.
this is a highly priviledge place, and is not accessable by the lesser privileged ring 1 ring 2 ring 3.
the history of MS has been to confusicate or confound, operations, probably to make life difficult for unvetted progammers.

the summary point is, dont trust windows to leave anything the way it should be, so you must preserve the windows state call your asm routine do the routine then offset the stack pointer to where you saved the machine state, pop it all back into registers from stack then Ret back to the windows execution context.

windows can create multiple threads of execution, so that even though ASM routine is executing, windows kernel will steal cpu time slices to do things then give the cpu back to your routine but with mangled register values.  this is why you should store registers on local variables. :greensml:
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 11:39:10 AM
Quote from: AK_AK on January 25, 2019, 10:58:02 AM
the windows kernel operates in a place called ring 0.
this is a highly priviledge place, and is not accessable by the lesser privileged ring 1 ring 2 ring 3.
the history of MS has been to confusicate or confound, operations, probably to make life difficult for unvetted progammers.

the summary point is, dont trust windows to leave anything the way it should be, so you must preserve the windows state call your asm routine do the routine then offset the stack pointer to where you saved the machine state, pop it all back into registers from stack then Ret back to the windows execution context.

windows can create multiple threads of execution, so that even though ASM routine is executing, windows kernel will steal cpu time slices to do things then give the cpu back to your routine but with mangled register values.  this is why you should store registers on local variables. :greensml:
am not talking about kernel mode , and am not using any previliged instructions to worry about registers state !
anyways , i just needed an answer and i found it  :t
Title: Re: Fifth tutorial of iczelion series
Post by: hutch-- on January 25, 2019, 12:08:00 PM
There is a bit of folklore going on here. Task switching from one process to another is controlled by the OS on a thread by thread basis but this much you can be sure about, the register usage in one thread has absolutely no effect on the register usage of another thread. Within a single thread you have register usage that is specified in what is called the Intel "Application binary interface" ABI which the entire 32 bit OS functionality strictly adheres to. There are special cases where a programmer can bypass this but only in code that does not directly interact with the OS.

Put simply, you can make a mess of EAX, ECX and EDX but so can anything you call, the rest MUST be preserved as the OS is written according to the ABI and you risk serious crashes if you try and differ from the OS.
Title: Re: Fifth tutorial of iczelion series
Post by: AK_AK on January 25, 2019, 12:13:42 PM
thanx for the deeper precision hutch :t I was attemping to explain to abdel how windows can interfere with registers contents, the deeper principle youve explained provides a hieghtened understanding of the environment that we must negotiiate with our code.
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 12:20:07 PM
Quote from: hutch-- on January 25, 2019, 12:08:00 PM
There is a bit of folklore going on here. Task switching from one process to another is controlled by the OS on a thread by thread basis but this much you can be sure about, the register usage in one thread has absolutely no effect on the register usage of another thread. Within a single thread you have register usage that is specified in what is called the Intel "Application binary interface" ABI which the entire 32 bit OS functionality strictly adheres to. There are special cases where a programmer can bypass this but only in code that does not directly interact with the OS.

Put simply, you can make a mess of EAX, ECX and EDX but so can anything you call, the rest MUST be preserved as the OS is written according to the ABI and you risk serious crashes if you try and differ from the OS.

thank you for clearing out this point Mr.Hutch  :biggrin:
Title: Re: Fifth tutorial of iczelion series
Post by: AK_AK on January 25, 2019, 12:55:43 PM
  I just followed the breadcrumbs and came up with this for now.

https://en.wikipedia.org/wiki/Application_binary_interface

Im just reading it right now but i left this here so if anyone else wants to take a few swipes at the horse, im sure its deader than a doornail, but we could branch the thread here.

  Pardon me ahead of time for being unfamiliar with proper places and limits of topics, but feel free [Hutch] to editorialize if that will keep things tidier in here.
im now off to see if we have a refresher regarding the architechture of win32/64 . 
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 02:27:45 PM
i don't want to post so many threads about iczelion tutorials ! this will be annoying
so after your permission Mr.Hutch , i would like to post my questions about his tutorials on this thread  :icon_redface:
you can edit or delete whatever you want this is just a suggestion  :icon_rolleyes:
so many questions are in my head right now !
Tutorial 7 : i guess his running too fast and missing some points that needs to be  clarified  :(  :(  :(

http://win32assembly.programminghorizon.com/tut7.html

first question :

POINT STRUCT
    x   dd ?
    y   dd ?
POINT ENDS

in Win32API help files

typedef struct tagPOINT { // pt 
    LONG x;
    LONG y;
} POINT;

clearly there is a difference between double word and long , long is 64bit in size , double word is 32bit
why there is such difference between difinitions ???
second question : is 'MouseClick' a constant ? i haven't found it in any place , it doesn't exist in help files nor MSDN , and when i try to replace it with another label for instance : "MC" i get this error :

error A2006: undefined symbol : MC

- third question :

wParam is 32bit in size , low word of wParam for "x" , high word of wParam for "y" !
for example : x = 1200 , y = 2400
wParam will be : 24001200
after moving its value to eax , and doing logical "and" we'll get :
eax will be = 00001200 <= 
same for y , but why we used shr eax,16 and not shr eax,8 ????

    .ELSEIF uMsg==WM_LBUTTONDOWN
        mov eax,lParam
        and eax,0FFFFh
        mov hitpoint.x,eax
        mov eax,lParam
        shr eax,16
        mov hitpoint.y,eax
        mov MouseClick,TRUE
        invoke InvalidateRect,hWnd,NULL,TRUE


please give me an answer am really really tired , i have read the tutorial more than 10 times  :icon_redface:  :(
Title: Re: Fifth tutorial of iczelion series
Post by: TBRANSO1 on January 25, 2019, 02:59:36 PM
[quote author=Abdel Hamid link=topic=7648.msg83441#msg83441 date=1548386865]
clearly there is a difference between double word and long , long is 64bit in size , double word is 32bit

All 32-bit code is 4 bytes, including long... all max type definitions of long in Windows 32-bit is 4 bytes. refer to here: https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types

Quote
second question : is 'MouseClick' a constant ? i haven't found it in any place , it doesn't exist in help files nor MSDN , and when i try to replace it with another label for instance : "MC" i get this error :


.data
ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0
MouseClick db 0         ; 0=no click yet


If I follow the code, which I've done this tutorial recently.  When the left click is detected, it sends a signal to the WndPrc, which at the end sets the MouseClick to true.  The Mouseclick is defined by the author as a constant 0 or false.  This sets it to true. Then in that same block, the reference to the Rectangle (window) is destroyed, and sends a signal to the the main, which detects and sends a signal back to the WndPrc to redraw things in the WM_Paint part.  If you see that the .IF MouseClick is TRUE ? part, it does the textout section and the MouseClick gets set back to false again.

I am not sure where MC comes from though, unless that is your code?

Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 03:27:36 PM
Quote from: TBRANSO1 on January 25, 2019, 02:59:36 PM
I am not sure where MC comes from though, unless that is your code?
pardon me , i haven't seen MouseClick at the top , i like to type the whole code to remember
just forget about "MC" , thanks for your cooperation you saved me  :bgrin:
now i only need to know why he used shr eax,16 ?
he said :

Because y-coordinate is the high word of lParam, we must put it in the low word of eax prior to storing it in hitpoint.y. We do this by shifting eax 16 bits to the right.

suppose wParam has the high word y = 3000 , when we move wParam to eax
eax = 30000000
now i need to move "y" to the low word of eax to get the result below :
eax = 00003000
i tried to simulate this in a debugger but the register will have the value zero after shift ? is it normal , or am doing something wrong  :redface:
Title: Re: Fifth tutorial of iczelion series
Post by: hutch-- on January 25, 2019, 03:34:59 PM
> clearly there is a difference between double word and long , long is 64bit in size , double word is 32bit

In 32 bit, LONG is a 32 bit data size. In assembler DWORD and LONG are no different, they fit the same 32 bit register or memory. The distinction between signed and unsigned does not exist in the data, only how you evaluate it with conditional jumps, the difference between JA versus JG.
Title: Re: Fifth tutorial of iczelion series
Post by: TBRANSO1 on January 25, 2019, 03:45:02 PM
You are at the same spot I was a month ago.  I came into this world of assembly about 2 months ago.  I came from using HLL languages like Ruby, Python, Java, the C's.  While I had an introduction to assembly in school, being that MASM32 is a Microsoft approach and I never did anything with the MS libraries except the C RT stuff, I mostly did Linux POSIX C stuff.

I started his tutorials but found that I had lots of learning to do.  I turned to ol' Mr. Softie's online MSDN library and the Internet for help.  Go here and get learned up on more of the basics of Windows:
https://docs.microsoft.com/en-us/windows/desktop/winmsg/windows
https://docs.microsoft.com/en-us/windows/desktop/learnwin32/learn-to-program-for-windows
https://docs.microsoft.com/en-us/windows/desktop/winmsg/windowing

I can't find it now, but somewhere in there it defines the upper wParam and lower lParam.  The upper 16-bits of the 32-bit message that the main app sends to the WndPrc is used for certain signals and the lower 16-bit part is used for most of the rest.  In order for the correct signal to be read, it must be either truncated to the lower params by converting it to a WORD size, or shifting to the right for the Upper part and converting it to WORD size.

I made a macro based on the LOWORD and HIWORD C++ macros, but then I read later that MASM has LOWWORD and HIGHWORD macro directives built in, study those too.  Either way, you could use a mask like 00000FFFFh for the lower and/or just use the shl operator to move the bits down and then use the mask... that's all those C++ macros do.
Title: Re: Fifth tutorial of iczelion series
Post by: Abdel Hamid on January 25, 2019, 03:54:09 PM
@Hutch-- , thank you sir for the good information
@TBRANSO1 , thank you so much for the bunch of informations
i have no experience in HLL , is it okay to read what you mentioned ?
Title: Re: Fifth tutorial of iczelion series
Post by: TBRANSO1 on January 25, 2019, 04:16:55 PM
Quote from: Abdel Hamid on January 25, 2019, 03:54:09 PM
@Hutch-- , thank you sir for the good information
@TBRANSO1 , thank you so much for the bunch of informations
i have no experience in HLL , is it okay to read what you mentioned ?

As for the documentation, I have had to read it multiple times and in short bursts, this information is saturated and makes you jump to different links. Spend time with though, you'll get it.

As for reading code... I struggled to read Win32 Kernel code and still do, since it's got so much unique language and conventions.  Furthermore what confused me is the certain libraries refer to the same data type, like a DWORD or DWORD PTR differently.  It was hard at first, it's getting easier now.  Reading C is pretty easy as it's straight forward, but reading Ruby or Python with a lot of concepts like monkey-patching, metaprogramming, wrappers, method-missing techniques will pull your hair out... as you really don't know sometimes what the author or authors were thinking, where the code begins or ends, jumping around like a crazy chicken from one file to another... one function here on this file, then calls a reference to a another to another to another then mangles the methods with monkey-patching, and metaprogramming, different levels indirection, it's crazy.

You will do fine, you seem smart enough and motivated.