News:

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

Main Menu

Short global variables

Started by jj2007, July 23, 2012, 07:40:27 AM

Previous topic - Next topic

jj2007

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.

dedndave

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

hutch--

 :biggrin:

In applications where a single bitmap can be over 100k, you worried about 3 bytes in a MOV instruction ? Come on.  :P

jj2007

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.

mywan

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.

Ryan

How many cycles does each version take?

hutch--

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 ?

jj2007

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.

Ryan

Just out of curiosity, what file system/cluster size do you use?

qWord

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:
MREAL macros - when you need floating point arithmetic while assembling!

Ryan

Nice!  His file system uses a cluster size of 1/512 of a sector!

qWord

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
MREAL macros - when you need floating point arithmetic while assembling!

Ryan

How do you get the assembler to truncate the unused bytes at the end of the executable?

hutch--

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.

mywan

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.