News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

ACCEL structure

Started by donkey, January 06, 2005, 04:40:25 AM

Previous topic - Next topic

donkey

Hi Hutch,

A recent question prompted me to find out about the ACCEL structure and I have found that the info at MSDN is misleading and the structure as it appears in MASM32 and the Window.inc for GoAsm is incorrect. It currently is...

ACCEL STRUCT
  fVirt DB ?
  key   DW ?
  cmd   DW ?
ACCEL ENDS


In order for it to work properly it must be changed to...

ACCEL STRUCT
  fVirt DB ?
  pad0  DB ?
  key   DW ?
  cmd   DW ?
ACCEL ENDS


Apparently this is because MS is relying on the automatic alignment to WORD sized elements, something that neither MASM32 nor GoAsm does.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

Thanks for the info. MASM can change the alignment of a structure by adding the alignment size after the struct statement. I wonder if this works OK.

ACCEL STRUCT WORD
  fVirt DB ?
  key   DW ?
  cmd   DW ?
ACCEL ENDS
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Hi Hutch,

I'm not sure as I can't test it here but from a quick look at the MASM manual I don't think so because this is what it says...

QuoteAny padding required to reach the correct offset is added prior to allocating the field

So you would think it would end up being...

ACCEL STRUCT
  pad0  DB ?
  fVirt DB ?
  key   DW ?
  cmd   DW ?
ACCEL ENDS


Could be wrong about this though, you would have to test it with CreateAcceleratorTable and see if you can use the accel. keys...

.data
act    ACCEL <FCONTROL or FVIRTKEY, 0, VK_F12, 1001>
       ACCEL <FCONTROL or FVIRTKEY, 0, VK_Z, 1002>

.code
; Message pump
invoke CreateAcceleratorTable,offset act,2
mov [hAccel],eax

@@:
invoke GetMessage, ADDR msg,NULL,0,0
or eax,eax
jz @F
invoke TranslateAccelerator,[hDlg],[hAccel],ADDR msg
or eax,eax
jnz @B
invoke IsDialogMessage, [hDlg], ADDR msg
or eax,eax
jnz @B
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp @B
@@:
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

MichaelW

The alignment value seems to work just as described in the MASM 6.0 Programmer's Guide. It makes sense that Microsoft would provide this capability because MASM is intended to work with the Microsoft HLLs, and not all of them expect the same alignment (I recall the DOS BASICs expecting byte-packed structures and C expecting word alignment).

    .486                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive
    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib
    include \masm32\macros\macros.asm
    .data
        _ACCEL STRUCT
          fVirt DB ?
          key   DW ?
          cmd   DW ?
        _ACCEL ENDS
        _accel _ACCEL <>
        _ACCELW STRUCT WORD
          fVirt DB ?
          key   DW ?
          cmd   DW ?
        _ACCELW ENDS
        _accelw _ACCELW <>
    .code
start:
    print uhex$(offset _accel.fVirt)
    print chr$(13,10)
    print uhex$(offset _accel.key)
    print chr$(13,10)
    print uhex$(offset _accel.cmd)
    print chr$(13,10,13,10)
    print uhex$(offset _accelw.fVirt)
    print chr$(13,10)
    print uhex$(offset _accelw.key)
    print chr$(13,10)
    print uhex$(offset _accelw.cmd)
    print chr$(13,10,13,10)
    mov   eax, input("Press enter to exit...")
    exit
end start

Output:

00403000
00403001
00403003

00403005
00403007
00403009

Press enter to exit...

eschew obfuscation

Relvinian

I decided to play with this a little bit for you guys with both the MASM and the C/C++ side of things. Here is what I found out:


C/C++ stack definition (with default Visual C++ alignment of 8-byte per struct)

ACCEL theTest[3] =
{
   {1,1,1},
   {2,2,2},
   {2,2,2},
};


Memory output of the above:

address       bytes (8 count)
---------------------------------------
0x0012fe70    01 cc 01 00 01 00 02 cc
0x0012fe78    02 00 02 00 03 cc 03 00
0x0012fe80    03 00 cc cc cc cc cc cc

As you see from the memory output, this definition of "theTest[3]" takes 24 bytes of memory from my stack. Each variable in the structure uses two bytes for a total of 18 bytes plus padding to align at 24.

The 'cc' is what the memory is first initialized to before the variables get populated. So you'll notice that the first one is padded because you see the 'cc' after the first byte (to align each variable on the greatest size in the structure). The would change if there was a DWORD variable in the structure.

Here is the same thing done in MASM with assembling with the following parameters for ML.EXE (using the default alignment of one):
   ml.exe /c /Cp /Cx test.asm

Memory output for the ASM equivalent:
0x0012fe00   01 01 00 01 00 02 02 00
0x0012fe08   02 00 03 03 00 03 00


As you can see the two memory areas are completely different so when you get into the Windows API routines, the values will fail or depending on what API is called, could even crash your application.

Unless you specify /Zp8 (8-byte alignment) on the ML.EXE command line, you are defaulting to ONE byte alignment which will cause problems which structures that have alignment requirements (as in the case with ACCEL).

Instead of modifying the ACCEL structure in MASM, it is best to change the assembling options to set the structure alignments to eight (which is what Visual Studio is defaulted to) to assemble the specified files which have structures. That way, you'll get the correct alignment where it is needed.

Hope this helps you guys.

Relvinian

MichaelW

It looks to me like the option should be /Zp4, even though /Zp8 seems to produce the same result. Per the MASM 6.0 and 6.1 Programmer's Guides:

The only values accepted for alignment are 1, 2, and 4.

eschew obfuscation