News:

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

Main Menu

"Hello masm32", not a BOT, new member

Started by LordAdef, January 22, 2017, 09:42:24 AM

Previous topic - Next topic

LordAdef

Thanks,

I´ll have a closer and careful look at the debugger.

QuoteDon't make this a habit, though: You risk losing a lot of time chasing single bytes instead of concentrating on good code.
Ok. But it´s always a good habit to learn from the beginning I think. The most precious thing I´m learning from you is the "mindset". If you don´t learn this, one will never become a good Assembly programmer.

LordAdef

Update, prog3


Prog3, ScrollingFromFile, uses 2 procedures: pLoad (my loading code from prog2) and pConsoleEngine (adapted from my prog1, it generates the scrolling effect on the console)

1. It loads the file, parse it and fills the array.
2. I put all the engine code into the procedure and made its variables as LOCALS, to encapsulate a bit (right design choice?)
3. I turned all constants into High Caps to be more consistent
4. Made the changes based on JJ´s comments
5. The lenght (cWIDTH) and number of lines (cHEIGHT) are still hard coded. I might work on this next, although my array declaration asks for constants:

   
Quote.const
    cWIDTH  EQU    20                           ;num of Chars in a line
    cHEIGHT EQU    60                           ;num of Lines 

.data
    Map        db  cHEIGHT  dup(cWIDTH dup(?),0)   ;Main array, adds 0 for termination
    Filename   db  "Map1.txt",0
4. When running the prog, we need to manually adjust the size of the console window to fit the current 60 lines. I didn´t bothered to search about this for now
5. Last but not least, I made a small Homage to JJ in the scrolling text :greenclp:

I might soon be porting this onto a Windows frame.


hutch--

There is a context for how and why some of the older fellas still do some things the way it was done over 25 years ago. With pre-486 processors (1990) you actually DID count cycles and with very slow 8088 and slightly later hardware, packing code into smaller layouts by instruction choice was a viable form of optimisation for writing memory image COM files in MS-DOS. The problem was that this changed with the 486DX which introduced the concept of a pipeline where the action switched to "scheduling" instructions through that pipeline in the most efficient order.

It also entailed abandoning some of the old instructions because while they still worked, the internal guts of the processors ran faster if you stuck to simpler preferred instruction set that Intel published. Packing instructions in the right order meant the processor did not have to stop and wait for a result which caused a stall and this became more important with multiple pipeline later processors. Some of this varied with different processors but the general direction from the 486 era onwards was to use simpler instructions in the right order, minimising branching and reducing the number of memory operations.

You can pick up bad habits like using out of date instructions (xchg, movsb/w/d/q and stosb/w/d/q without the REP prefix) and various others but it will come at the price of producing sub standard code that is often not as fast as junky high level code. You chase reduced instruction counts where you can by removing redundancies in your code but do not fall for just chasing code sized reduction as it does not produce useful results and often slows your code down.

jj2007

Quote from: hutch-- on February 02, 2017, 03:12:24 PMYou can pick up bad habits like using out of date instructions (xchg, movsb/w/d/q and stosb/w/d/q without the REP prefix)

Nothing of what Hutch writes is entirely wrong, but the context matters a lot. Inside a tight loop that runs a Million times, one should indeed be careful. In all other cases, xchg eax, reg32 saves a byte at no additional cost, and stosd is a wonderful instruction for storing a bunch of handles into their global variables. And there are numerous other examples where old instructions can be the right ones.

There are also the incredibly old inc and dec instructions, which trigger every now and then an exchange of religious views on the speed difference to add and sub, see here for a recent example, or here for a less recent one (why is "add" faster than "inc", April 2006).

If you want to see super-fast super-modern "junky high level code" in action, install Visual Studio Community. The good news, it's free, but warning, your hardware is probably too old for such modern code, and it may take a while until you see the editor in front of you 8)

hutch--

 :biggrin:

And when you add up all of the size reductions gained by picking old slow instructions, it still does not add one 512 byte section to an executable. Start down the slippery slope of writing garbage and you will end up with garbage.  :P

jj2007

Quote from: hutch-- on February 02, 2017, 10:43:02 PMAnd when you add up all of the size reductions gained by picking old slow instructions

These instructions are old, but they don't slow down your code as long as you don't do really stupid things like squeezing them into a tight loop. On the contrary, every saved byte that does not end up in the instruction cache may indeed make your code faster.

hutch--

 :biggrin:

> may indeed make your code faster.

This is indeed a big IF when code cache performance is easily testable. Loop unrolling is a perfect mechanism to see where the performance limit is. Keep increasing the level of unrolling until the code goes not faster then keep unrolling the loop code until it gets slower and you will find the cache limit of the particular processor you are using. Test it across a range of hardware and you will start to get averages and the code you put into production will hit somewhere in the middle of cache performance.

The assumption that code sized effects are cumulative across an entire application is unsound, it is always local to where the code occurs. With modern hardware, close range code size almost exclusively does not matter where instruction choice will bite you on that arse if you use old DOS era junk. Develop the habit of tolerating garbage to save a few bytes here and there and you will end up producing garbage.

jj2007

REPEAT 1000
 
Quote from: jj2007 on February 03, 2017, 02:54:05 AMThese instructions are old, but they don't slow down your code as long as you don't do really stupid things like squeezing them into a tight loop.
Quote from: hutch-- on February 03, 2017, 06:42:04 AMDevelop the habit of tolerating garbage to save a few bytes here and there and you will end up producing garbage.

ENDM

TWell

I think that people use assembler to optimize code.

Those who want to generate garbage to waste CPU resources, there is already Java for that.
Just couple lines of code and lot of memory and CPU cycles wasted.

hutch--

 :biggrin:

> REPEAT 1000

Repetition does not make substandard code work any better. Write garbage, get garbage.  :P

Tim,

You can write poor code in any language, assembler is certainly not immune from producing slow sloppy code as many have found out.

jj2007


hutch--

 :biggrin:

> Did I ever insult you, Hutch?

Regularly but its useful for folks learning to understand that there is a wide variety of opinion in coding techniques and the only one that matters is their own.  :P

LordAdef

Update: prog4, the scrolling ported to windows.

I use Iczelion´s code for the Window and changed it to my taste.
Run it and move you mouse over the window to trigger the scroll.

The rendering code is within the Window message: .ELSEIF uMsg==WM_PAINT:

Quote.ELSEIF uMsg==WM_PAINT
        invoke BeginPaint,hWnd, ADDR ps
        mov    hdc,eax
        ;================================ FONT ======================================
        invoke CreateFont,16,0,0,0,400,0,0,0,OEM_CHARSET,\
                               OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
                               DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
                               ADDR FontName
        invoke SelectObject, hdc, eax
        mov    hfont,eax
        RGB    255,255,255
        invoke SetTextColor,hdc,eax
        RGB    50,50,50
        invoke SetBkColor, hdc,eax
       
        ;================================ RENDERER ===================================

        xor edi, edi                              ;Loop
        mov esi, 1                                ;esi= y coord of line 1
           @@:
            mov hitpoint.x, 300
            m2m hitpoint.y, esi
                                                  ;--- MOD ArrayLineOffset & Multiply ---
            mov eax, ArrayLineOffset                  ;MOD ArrayLineOffset
            mov ebx, cHEIGHT
            cdq                             
            div ebx
            mov ArrayLineOffset, edx                  ;MOD value
   
            mov eax, ArrayLineOffset
            mov ebx, cWIDTH
            mul ebx                                   ;get array. eax= array offset (index)
                           
            invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR Map+[eax], cWIDTH
   
            add esi, 15                               ;(tYPos)
            inc ArrayLineOffset
            inc edi                                   ;loop increment
            cmp edi, cHEIGHT   
            jb @B
        invoke SelectObject,hdc, hfont                ;closes font
        invoke EndPaint,hWnd, ADDR ps                 ;End Paint
    .ELSEIF     uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL       
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF


:icon_confused: The prog has a problem though :icon_confused::

It starts running with 3.150 bytes, but the memory usage keeps getting higher and higher. Around 10.000 something happens... (same result if I loose the font code)

ps: Guys, I just completed my first week in MASM!

fearless

CreateFont would ideally be placed in some other part of the program, at startup, initialization routine etc, where the font handle is saved.


        invoke CreateFont,16,0,0,0,400,0,0,0,OEM_CHARSET,\
                               OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
                               DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
                               ADDR FontName
        mov    hfont,eax


Can be moved to WM_INITDIALOG or something else.

The old font object is probably still being leaked when selecting and clearing it i suspect. I would have an hOldFont handle when using the SelectObject and restore once finished with it.

Something like:

Invoke SelectObject, hdc, hFont
mov hOldFont, eax

.
.
. do some stuff with text and font
.
.
.
Invoke SelectObject, hdc, hOldFont



Of course there could be a resource leak elsewhere or something else ive forgotten.

LordAdef

You are totally right!  I'll move the font code  to another place. I thought of that but didn't implemented. Even I will need more than one font.

I commented the font code and the leak persists