News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Fifth tutorial of iczelion series

Started by Abdel Hamid, January 25, 2019, 08:11:28 AM

Previous topic - Next topic

Abdel Hamid

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

AK_AK

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.

Abdel Hamid

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:

TBRANSO1

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.

Abdel Hamid

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  ;)

jj2007


Abdel Hamid

Quote from: jj2007 on January 25, 2019, 09:25:20 AM
Read The "register gets trashed" trap here.
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 


AK_AK

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

Abdel Hamid

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

AK_AK

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:

Abdel Hamid

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

hutch--

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.

AK_AK

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.

Abdel Hamid

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:

AK_AK

  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 .