Global variables bloat the code:
mov hMain, 123 ; 10 bytes
mov [ebx+4], 123 ; 7 bytes
So I wrote a macro that defines them relative to ebx. Usage is very simple, just declare them in the .data? section as if they were LOCALs:
SetGlobals hMain:HWND, hButton1:HWND, hButton2:HWND, hStatic:HWND, hEdit:HWND
SetGlobals hButFnt:HWND, hAccels:HWND, msgCount, opSubClass
SetGlobals rc:RECT, msg:MSG, wc:WNDCLASSEX, gBuffer[1024]:BYTE
....
.code
start: SetGlobals ; no args makes ebx point to the variables defined above
...
WndProc proc uses ebx esi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
SetGlobals ; do not use ebx below, unless pushed & popped
SWITCH uMsg
...
mov hMain, eax ; use like a normal global variable, but 3 bytes shorter
This technique is useful when you often use global variables. It also opens the option to use the same set of variables in multi-thread applications (i.e. just copy the first global set to a second location for thead #2 and let ebx point to it).
The "short" range is [ebx-128] to [ebx+127], i.e. 64 DWORD variables; if you need a fat general purpose buffer, put it at the end, so that its start address will be inside the range.
I attach a full example similar to \masm32\examples\exampl01\generic\generic.asm
The next release of MasmBasic will contain the SetGlobals and Enum macros, too. The attached source does not use MasmBasic, though, just plain Masm32.
good thinking :t
i try to use a register to address larger structures, like WNDCLASSEX
also - i often put many of my globals into structures
it helps keep them organized and you can address them with a register
true that you don't need a structure to do this - but it makes the code cleaner
here are a few examples from my map viewer...
ControlHandles STRUCT
hStatusBar HWND ?
hRightBox HWND ?
hVScrollBar HWND ?
hHScrollBar HWND ?
hLeftBox HWND ?
hTrackBar HWND ?
hImageWin HWND ?
ControlHandles ENDS
CoordInfo STRUCT
s SCROLLINFO <>
; cbSize dd ? ;sizeof SCROLLINFO
; fMask dd ? ;SIF_RANGE or SIF_PAGE or SIF_POS
; nMin dd ? ;0
; nMax dd ? ;(zoomed image dimension - 1) + ((image window dimension - 1) and -2)
; nPage dd ? ;image window dimension
; nPos dd ? ;top or left image window coordinate
; nTrackPos dd ? ;thumb track position
uImgWinCent dd ? ;image window center (unzoomed image coord) for "Center" display
uCursorLoc dd ? ;cursor location for "Current" display
uUnzoomSize dd ? ;unzoomed image dimension
uZoomedSize dd ? ;zoomed image dimension
nGrabOffset dd ? ;(cursor position - scroll position) when grabbed
nOriginDest dd ? ;destination coordinate for StretchBlt
nSizeDest dd ? ;destination dimension for StretchBlt
nOriginSrc dd ? ;source coordinate for StretchBlt
nSizeSrc dd ? ;source dimension for StretchBlt
uScBarSize dd ? ;scrollbar dimension
lpStatusBar dd ? ;status bar info pointer
uScreenSize dd ? ;screen dimension
uFrameSize dd ? ;frame dimension
CoordInfo ENDS
CoordinateGroup STRUCT
h CoordInfo <>
v CoordInfo <>
CoordinateGroup ENDS
:biggrin:
In applications where a single bitmap can be over 100k, you worried about 3 bytes in a MOV instruction ? Come on. :P
Quote from: hutch-- on July 23, 2012, 09:31:18 AM
In applications where a single bitmap can be over 100k, you worried about 3 bytes in a MOV instruction ? Come on. :P
Well, recently I was accused of wasting precious speed with some push/pop pairs ;-)
It's the fun of testing the limits, Hutch. Why else are we here in this forum??
Besides, I wanted to create a GUI example that looks a bit more concise and more modern than \masm32\examples\exampl01\generic\generic.asm.
Even when I say to hell with it, I'm going the easy route, I still want to know how much efficiency I'm am trading for that ease.
How many cycles does each version take?
JJ,
> Besides, I wanted to create a GUI example that looks a bit more concise and more modern than \masm32\examples\exampl01\generic\generic.asm.
Do you mean like masm1k.asm ?
It's more a proof of concept than anything else, and an extension of Dave's structures method (which I also frequently use) to all global variables.
Re trading,
- you need typically two mov ebx, offset globalvars (the SetGlobals without args does that), one in the startup code plus one in the WndProc (assuming no other callbacks).
- in case you need ebx in an innermost loop, you cannot use global variables there
+ shorter code anywhere else,
+ with a chance of getting faster code through fitting more into the CPU cache
+ same syntax for local and global variables
+ variables in WndProc remain valid for the next message (e.g. a RECT)
+ cleaner code for multi-threaded apps (i.e. you can use the same variable names for different memory areas)
It looks a bit different, though :biggrin:
> Do you mean like masm1k.asm ?
masm1k is a "naked" window; the example posted above has a few controls and handles messages etc
> How many cycles does each version take?
There is no difference, except if you have an innermost loop that fits into the CPU cache for the "short globals" version but doesn't for the "long" one. There is certainly no measurable difference for the handling of WM_xxx messages in the WndProc.
Just out of curiosity, what file system/cluster size do you use?
Quote from: Ryan on July 23, 2012, 10:25:33 PM
Just out of curiosity, what file system/cluster size do you use?
He has create his own FS that allows a cluster size of 1 Byte - the days of oversized and byte wasting clusters are over :biggrin:
Nice! His file system uses a cluster size of 1/512 of a sector!
Quote from: Ryan on July 23, 2012, 10:45:51 PM
His file system uses a cluster size of 1/512 of a sector!
When interpreting all sectors as a byte stream, you can choose whatever cluster size without losing any byte in the sectors. :P
How do you get the assembler to truncate the unused bytes at the end of the executable?
You don't, its the linker that produces the final EXE file but its still not good practice, at least some OS version don't like misaligned ends of EXE files and some AV scanners have nightmares with such mods.
I think a lot of AV scanners like to scare their customers into thinking their doing them a favor. Some scanners, if you set them to go after ad cookies, will label them viruses, tracking.exploit, or something similar to. More marketing than substance. What they will not say is how easy it is to stash a 10 gig file on a machine that the scanner can't even find, much less scan.
Quote from: qWord on July 23, 2012, 10:42:22 PM
Quote from: Ryan on July 23, 2012, 10:25:33 PM
Just out of curiosity, what file system/cluster size do you use?
He has create his own FS that allows a cluster size of 1 Byte - the days of oversized and byte wasting clusters are over :biggrin:
Quote from: Ryan on July 23, 2012, 10:45:51 PM
Nice! His file system uses a cluster size of 1/512 of a sector!
Hutch,
Could you please move these posts to their proper place (http://masm32.com/board/index.php#c7)? Afterwards, please delete this one (by the way: the old forum used to have a delete button - where is it gone?)
Thanks.
No need, the Workshop is a place for general discussion and many topics wander from their original subject.
My apologies. I was trying to get a feeling for pros and cons. I got a bit carried away. I'm sorry.
Jochen, it's cute technique simplifying the code readability, besides it could have its use, for instance, in an inner loops of some heavy multithreaded apps (for accessing global vars controlling the threads each from another) :t
Quote from: Antariy on July 24, 2012, 12:29:28 PM
Jochen, it's cute technique simplifying the code readability, besides it could have its use, for instance, in an inner loops of some heavy multithreaded apps (for accessing global vars controlling the threads each from another) :t
Thanks, Alex, that could indeed be the most interesting application for this technique.
@Ryan: Thanks for the clarification :icon14:
it can do a lot for you
if you look at the structures i posted earlier, you will see that i have horz and vert scroll info structs
i use the same code for both axis
at the beginning, i just grab a pointer into the structure
if it is horz scroll, the scroll info struct is right there
if it is vert scroll, i add the struct size and - bang - i am pointing at vert scroll info
then - both use the same code
again - with the handles...
when the child windows and controls are created in a loop, the handles fill the structure
in WM_SIZE, i use an index into the handle struct to adjust window/control sizes and positions
so - it saves more than a few bytes :t
Quote from: dedndave on July 25, 2012, 08:04:39 AM
so - it saves more than a few bytes :t
Dave,
good point and a really cool technique. :t
Gunther