NASM - The Netwide Assembler

Related Projects => NASMX => Topic started by: encryptor256 on January 17, 2014, 06:27:26 PM

Title: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 17, 2014, 06:27:26 PM
Hello!

Problemo:

Today i found a nasty surprise, that my structures are aligned incorrectly,
some structure sizes were not correct and structure member alignment too. :D
So, i went to investigate.

Each of my structure and member offsets i tested in Win64 Pelles C,
structures like PAINTSTRUCT, MSG, CREATESTRUCTA and so.

Then i tested with NASMX, to find out, if there are correct structure sizes, and i found that there is not too.

Attached modified demo1.asm, that gives a message boxes:
1. PAINTSTRUCT_size: 68 (should be 72)
2. LOGFONT_size: 60 (should be 60)
3. MSG_size: 40 (should be 48)
4. Wrong(wParam) MSG_offsets:  hwnd: ( 0 ), message: ( 8 ), wParam: ( 12 ), lParam: ( 20 ), time: ( 28 ), pt.x: ( 32 ), pt.y: ( 36 )

This is how it should be:
MSG.hwnd, size 8, offset 0
MSG.message, size 4, offset 8
MSG.wParam, size 8, offset 16
....
After MSG.message there needs to be a 4x padding bytes, so, when touching wParam, then , the touch, is aligned on 8x byte boundaries.

MSDN: Aggregates and Unions (http://msdn.microsoft.com/en-us/library/9dbwhz68.aspx):

Some ideas, structure size 44 + 4x bytes of padding:
Code: [Select]
MSG.hwnd equ (0)
MSG.message equ (8)
MSG.wParam equ (8+(4+4))
MSG.lParam equ (8+(4+4)+8)
MSG.time equ (8+(4+4)+8+8)
MSG.pt.x equ (8+(4+4)+8+8+4)
MSG.pt.x equ (8+(4+4)+8+8+4+4)
So, last offset is 40, which estimates in 44 bytes of structure size!
Largest member unit set size is 8.
L = 8
SZ = 44
X = SZ - SZ / L * L = 44 - 40 = 4    ; Determine if SZ divides with L without a remainder, which X becomes.
IF X != 0
 X = L - X = 4
ENDIF
Final structure size:
SZ = SZ + X = 44 + 4 = 48.

This is how it should be,
a testing macro named: structureoffsets
Code: [Select]
%macro structureoffsets 3-*
      %define structname %1
      %assign loopcount ((%0-1)/2)
      %assign alignment 1


      ; Determine alignment
      %rotate 1
      %rep loopcount
            %if (%2 > alignment) && (%2 <= 8)
                  %assign alignment %2
            %endif
            %rotate 2
      %endrep

      ;%warning ALIGNMENT alignment

      ; First pair doesnt count
;       %assign %$structoffset 0
;       %rotate 1
;       %define %[%$structname].%[%1] %$structoffset


      %assign correctioncount 0
      %define max ((%0-1)/2)
      ;%define structname %1
      %assign structsize 0
      %rotate 1
      %rep max
            %if %[%2] = 8
                  %assign mod (%[structsize]-(%[structsize]/8)*8)
                  %if mod != 0
                        %assign structsize %[structsize]+(8-%[mod])
                        %assign correctioncount 1
                  %endif
                  %undef mod
            %endif
            %define %[structname].%[%1] %[structsize]
            %assign structsize structsize+%[%2]
            %rotate 2
      %endrep
      ; ---
      %assign mod (%[structsize]-(%[structsize]/%[alignment])*%[alignment])
      %if mod != 0
            %assign structsize %[structsize]+(%[alignment]-%[mod])
      %endif
      %undef mod
      %undef correctioncount
      ; ---
      %define %[structname]_SIZE %[structsize]
      %warning "zzzstruct:" %[structname] %[structname]_SIZE
      %undef max
      %undef structname

%endmacro

These are structures,
defined by test macro structureoffsets:
Code: [Select]
structureoffsets WNDCLASSEXA,\
                cbSize,4,\
                style,4,\
                lpfnWndProc,8,\
                cbClsExtra,4,\
                cbWndExtra,4,\
                hInstance,8,\
                hIcon,8,\
                hCursor,8,\
                hbrBackground,8,\
                lpszMenuName,8,\
                lpszClassName,8,\
                hIconSm,8

structureoffsets MSG,\
                hwnd,8,\
                message,4,\
                wParam,8,\
                lParam,8,\
                time,4,\
                pt.x,4,\
                pt.y,4
;

structureoffsets POINT,\
                x,4,\
                y,4

structureoffsets CREATESTRUCTA,\
                lpCreateParams,8,\
                hInstance,8,\
                hMenu,8,\
                hwndParent,8,\
                cy,4,\
                cx,4,\
                y,4,\
                x,4,\
                style,4,\
                lpszName,8,\
                lpszClass,8,\
                dwExStyle,4

structureoffsets RECT,\
                left,4,\
                top,4,\
                right,4,\
                bottom,4

structureoffsets PAINTSTRUCT,\
                hdc,8,\
                fErase,4,\
                rcPaint,RECT_SIZE,\
                fRestore,4,\
                fIncUpdate,4,\
                rgbReserved,32
;

structureoffsets NMHDR,\
                hwndFrom,8,\
                idFrom,8,\
                code,4
;


%define LF_FACESIZE  32
structureoffsets LOGFONTA,\
                lfHeight,4,\
                lfWidth,4,\
                lfEscapement,4,\
                lfOrientation,4,\
                lfWeight,4,\
                lfItalic,1,\
                lfUnderline,1,\
                lfStrikeOut,1,\
                lfCharSet,1,\
                lfOutPrecision,1,\
                lfClipPrecision,1,\
                lfQuality,1,\
                lfPitchAndFamily,1,\
                lfFaceName,LF_FACESIZE


structureoffsets WINDOWPOS,\
                hwnd,8,\
                hwndInsertAfter,8,\
                x,4,\
                y,4,\
                cx,4,\
                cy,4,\
                flags,4
;


structureoffsets STARTUPINFOA,\
            cb,4,\
            lpReserved,8,\
            lpDesktop,8,\
            lpTitle,8,\
            dwX,4,\
            dwY,4,\
            dwXSize,4,\
            dwYSize,4,\
            dwXCountChars,4,\
            dwYCountChars,4,\
            dwFillAttribute,4,\
            dwFlags,4,\
            wShowWindow,2,\
            cbReserved2,2,\
            lpReserved2,8,\
            hStdInput,8,\
            hStdOutput,8,\
            hStdError,8

structureoffsets PROCESS_INFORMATION,\
            hProcess,8,\
            hThread,8,\
            dwProcessId,4,\
            dwThreadId,4

structureoffsets SECURITY_ATTRIBUTES,\
            nLength,8,\
            lpSecurityDescriptor,8,\
            bInheritHandle,8

This is output of definition in compile time,
it prints structure name and size, like MYSTRUCT SIZE:
Code: [Select]
structures.inc:15: warning: (structureoffsets:50) "zzzstruct:" WNDCLASSEXA 80
structures.inc:24: warning: (structureoffsets:50) "zzzstruct:" MSG 48
structures.inc:29: warning: (structureoffsets:50) "zzzstruct:" POINT 8
structures.inc:43: warning: (structureoffsets:50) "zzzstruct:" CREATESTRUCTA 80
structures.inc:49: warning: (structureoffsets:50) "zzzstruct:" RECT 16
structures.inc:60: warning: (structureoffsets:50) "zzzstruct:" PAINTSTRUCT 72
structures.inc:66: warning: (structureoffsets:50) "zzzstruct:" NMHDR 24
structures.inc:85: warning: (structureoffsets:50) "zzzstruct:" LOGFONTA 60
structures.inc:95: warning: (structureoffsets:50) "zzzstruct:" WINDOWPOS 40
structures.inc:117: warning: (structureoffsets:50) "zzzstruct:" STARTUPINFOA 104
structures.inc:123: warning: (structureoffsets:50) "zzzstruct:" PROCESS_INFORMATION 24
structures.inc:128: warning: (structureoffsets:50) "zzzstruct:" SECURITY_ATTRIBUTES 24

Here, SIZE OF PAINTSTRUCT in x64 (http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=5943.0), Jeremy Gordon find out, that there was a problem him too, with assembly and structure alignment definitions.

Bye!
Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 18, 2014, 07:55:11 PM
Thanks for the report, encryptor256!

One of the macros originally developed for structure alignment, NASMX_ALIGN ( reference this old thread (http://www.asmcommunity.net//forums/topic/?id=30146) ) was designed to partly solve that issue.  However, it was never fully implemented in all published structure definitions.  Subsequently, I've re-examined the source for the structure macros and can confirm we are not supporting x64 struct alignment properly.  :-[

I've not been 100% satisfied with that support and would much rather have the NASMX_RESERVE and NASMX_ENDSTRUCT macros become much smarter when dealing with structure alignment issues.  We'll obviously have to research this a bit further and rework it for the next release.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Bryant Keller on January 19, 2014, 09:50:34 PM
The problem with MSG.message is that it's defined as uint32_t instead of uint_t. Also, nasmx.inc has:

Code: [Select]
%ixdefine uint_t uint32_t
instead of:

Code: [Select]
%ixdefine uint_t uint%[__BITS__]_t
Which would probably be better.

I assume that this is also the problem with PAINTSTRUCT. Rather instead of using uint32_t it's using int32_t and should be using a int_t with the same int%[__BITS__]_t style definition in nasmx.inc.

Fair warning, I don't have Windows or a 64-bit machine and the best I could do is a quick "read through" of the current NASMX release in relation to these structures. I would also be willing to bet that this issue is affecting other structures in the Win64 platform.

Providing basic alignment padding shouldn't work much differently than UNION support does. You figure out the size of the largest member of the structure, then append an 'align %{$largest_member_size}, resb 1'. The difficult part would be doing this for every single member, this would resort to the same kind of late binding that I did with objects.inc (which is far from being a trivial task).
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 20, 2014, 05:27:05 AM
Hi!

can confirm we are not supporting x64 struct alignment properly.

Thanks, for the confirmation, now we know, officially, that there is small problem. :)

The problem with MSG.message is that...

MSG.message on Win64 remains 32bit, other members,
like hwnd, wParam, lParam are now 64bit, because,
they are pointers or they can hold a pointer,
for example WM_CREATE message delivers CREATESTRUCT pointer into lParam.

Well, we can say what ever we want, but we cannot deny the truth - The Problem Might Be The Whole Microsoft Windows. :D
Also Intel processors! Why do we have to support very very old CPU types, backward compability, come on!, let's fly with the wind and go forward in time!
Let's cut old cpu support and old Ms Windows base and go with acceleration!

Q: What's wrong with you, why are you insulting Intel and Microsoft?
A: I'm not! Intel, Microsoft and others, ... They are just a business!

Solution to structure alignment.
I think Win64 is built on C, so we have to learn, how C aligns structures (according to BITS),
then implement new nasm.exe command switch, something like: "-cstruct", which means,
when ever compiler finds structure, which starts with "struct" definition, then it aligns
the structure according to C rules, + according to __BITS__ too, so,
"-cstruct" + BITS 32 : defines structures and aligns them on 32 bit boundaries.
"-cstruct" + BITS 64 : defines structures and aligns them on 64 bit boundaries.

Q: Why do we have to support C structures in NASM?
A: Why not! NASM is built on that C\C++ thingy too, so, why couldn't we! :D

NASM switch "-s": redirect error messages to stdout.
NASM switch "-se": send output to email. :D
NASM switch "-sc": call me, when compile is done :D

Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 20, 2014, 06:08:16 PM
Let's cut old cpu support and old Ms Windows base and go with acceleration!

Unfortunately, there is a huge segment of the population out there still running Linux and WinXP on 32-bit machines.  We can't just suddenly force them all to upgrade, nor can we afford to ignore them as potential customers of ours.  Also, while there are very few, if any, 16-bit assembly programmer positions on the job market today, there are still classes ( as referenced by the various threads on these very forums ) that teach it to this day.

Solution to structure alignment.
I think Win64 is built on C, so we have to learn, how C aligns structures (according to BITS),

And therein you find the problem.  My research has shown no structure alignment requirements leaving the compiler writers free to implement it how they see fit.  Factor in the various operating systems and compilers available on the market today and we have quite a bit of non-standardness.  Think of the various alignment and packing command line switches and macros available to the developer to use when creating his or her structures and you'll find that it's going to be rather difficult to replicate in a portable way.

Since NASMX is limited to the subset of CPUs targeted by Nasm ( Namely, Intel x86 and x64 CPUs ) we can design towards a standard implementation and yet permit the flexibility of allowing choice to the developer - mainly in the area of pragmas and switches.  Thus, our first job is to implement natural alignment per structure member and overall correct alignment of structure size based on target CPU.  Secondly, we need to implement a way for programmers to modify the default behavior - eg: something along the lines of http://gcc.gnu.org/onlinedocs/gcc/Structure-Packing-Pragmas.html (http://gcc.gnu.org/onlinedocs/gcc/Structure-Packing-Pragmas.html).  Finally, we'll need to verify that our published definitions conform to the expectations of the OS itself since obviously some currently do not.

Q: Why do we have to support C structures in NASM?
A: Why not! NASM is built on that C\C++ thingy too, so, why couldn't we! :D

See my original suggestion in this thread (http://forum.nasm.us/index.php?topic=872.0).  Note, however, that Nasm's free-form basically allows us to define the structures however we see fit - which neatly side-steps the issue and puts the onus on the developer to work out alignment issues.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Bryant Keller on January 21, 2014, 12:48:27 AM
Solution to structure alignment.
I think Win64 is built on C, so we have to learn, how C aligns structures (according to BITS),
then implement new nasm.exe command switch, something like: "-cstruct", which means,
when ever compiler finds structure, which starts with "struct" definition, then it aligns
the structure according to C rules, + according to __BITS__ too, so,
"-cstruct" + BITS 32 : defines structures and aligns them on 32 bit boundaries.
"-cstruct" + BITS 64 : defines structures and aligns them on 64 bit boundaries.

Q: Why do we have to support C structures in NASM?
A: Why not! NASM is built on that C\C++ thingy too, so, why couldn't we! :D

The development of NASMX is largely independent of the Netwide Assembler. Early on, a design choice was made to not break backward compatibility with old NASM versions whenever possible, this is because distributions like Debian will only allow new versions of software into their repositories after the software has been stable for some time.

Another thing to keep in mind is that NASM doesn't technically support structures.  There are a lot of features that NASM has that aren't actually hard-coded in. If you look at the source code, you'll notice that there is a bunch of macros in a file called standard.mac (http://repo.or.cz/w/nasm.git/blob_plain/HEAD:/standard.mac), one of which is the implementation of STRUC and ENDSTRUC. These are loaded into the nasm.exe file at compile time so they are always available to you. As you can tell by that file, structure support is just some fancy macro wrapper for the absolute directive. This makes since because structures are just made up of a bunch of label offsets to its members.
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 21, 2014, 08:26:50 AM
Let's cut old cpu support and old Ms Windows base and go with acceleration!

there is a huge segment of the population out there still running Linux and WinXP on 32-bit machines.  We can't just suddenly force them all to upgrade

a design choice was made to not break backward compatibility

Okay, okay, i agree, i wasn't thinking straight on that, sorry for that,
i blame early morning, when i posted that hostile idea, to cut backward compatibility. :D

Another thing to keep in mind is that NASM doesn't technically support structures.  There are a lot of features that NASM has that aren't actually hard-coded in. If you look at the source code, you'll notice that there is a bunch of macros in a file called standard.mac (http://repo.or.cz/w/nasm.git/blob_plain/HEAD:/standard.mac), one of which is the implementation of STRUC and ENDSTRUC.

This is something new, i was thinking otherwise, but it seems, that it's now other-otherwise, was thinking, that "struct" is not a macro, but it is. :D

Well, it seems, you both, already have some bright ideas, about, how to solve structure alignment, at least that part where NASMX supported Win64, maybe.

Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 23, 2014, 02:47:52 AM
Ok.  I'm 99% finished with part 1 - correcting the struc alignment issue.
I'm still working on the union stuff which is rather broken at the moment but struc's are fine now I believe.
I'll work on part 2 - pack()'ing - later on.

Can you download a snapshot (http://sourceforge.net/p/nasmx/code/HEAD/tree/trunk/) and test please?

Confirmation is appreciated.

Thanks.
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 23, 2014, 08:32:08 AM
Ok.  I'm 99% finished with part 1 - correcting the struc alignment issue.
I'm still working on the union stuff which is rather broken at the moment but struc's are fine now I believe.
I'll work on part 2 - pack()'ing - later on.

Can you download a snapshot (http://sourceforge.net/p/nasmx/code/HEAD/tree/trunk/) and test please?

Confirmation is appreciated.

Thanks.

Confirm!

Tested some winAPI and custom made structures.
Verified by brains and compared against Win64 Pelles C (http://www.smorgasbordet.com/pellesc/).
Result:
Structure Alignment now is correct!
* Well, at least, didn't managed to break it by finding any miss alignments.

Structure size's and member offset's reported, are correct.
By correct, i mean, they were equal.

Added attachment: "win64_demo1.asm", a file, where i did some testing, this file was derived from NASMX/WIN64/DEMO1.

Here is Win64 Pelles C, structure size + alignment + offset tester code, can be used for other structures too:
Code: [Select]
        #define ins(x) wsprintf(buffer,"%s\r\n%s: %d",buffer,#x,(int)&m.##x - (int)&m)
#define sz(x) wsprintf(buffer,"%s\r\n%s: %d",buffer,#x,sizeof(x))
#define initial(x) wsprintf(buffer,"\r\nSize: %d\r\nAligned: %d\r\n",sizeof(x),__alignof(x))

char buffer[4096];

        // TEST: MSG
// -------------------------------------------
MSG m;

initial(MSG);

ins(hwnd);
        ins(message);
        ins(wParam);
        ins(lParam);
        ins(time);
        ins(pt.x);
        ins(pt.y);
MessageBox(0,buffer,0,0);

Structures tested and can be found in attachment or elsewhere: CREATESTRUCT, STARTUPINFO, WNDCLASSEX, MyStructureD, MyStructureC, MyStructureB, MyStructureA, PAINTSTRUCT, LOGFONT, MSG.

Bye.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 23, 2014, 02:49:10 PM
Thank you for your efforts, encryptor256.  8)

Now, can I ask another favor?  I'd like you to write a console app, using NASMX only, where the program tests the generated struc size and offsets against known values.  It needs to assemble in both 32 and 64-bit mode.  The values to compare against must be defined such that, for example, MSG.wParam offset will change depending on BITS.  The program should printf() a message if it finds an error and return a positive value, otherwise printf() a success message and return zero (0).

I would like to see quite a few self-made strucs that test for the various permutations - kind of like your MyStructureX - but be ruthless in definitions trying to break it.  If possible, only %include 'nasmx.inc' and %include 'test.inc'.

I would like to include this work into NASMX as a way to automate testing and to prevent any regressions of future changes.  Please ensure NASMX copyright with yourself as the author for the source code.  Thanks again for your hard work.
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 23, 2014, 04:30:10 PM
write a console app, using NASMX only, where the program tests the generated struc size and offsets against known values.  It needs to assemble in both 32 and 64-bit mode.  The values to compare against must be defined such that, for example, MSG.wParam offset will change depending on BITS.  The program should printf() a message if it finds an error and return a positive value, otherwise printf() a success message and return zero (0).

I would like to see quite a few self-made strucs that test for the various permutations - kind of like your MyStructureX - but be ruthless in definitions trying to break it.  If possible, only %include 'nasmx.inc' and %include 'test.inc'.

Well, it seems like, our minds work with different frequencies, and my english is too bad, to understand the task.
It will take, too much time, to find out, what's on your mind.
AND, task is, too specific, to NASMX, cannot do it, don't have a big experience with it, sorry.

Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 23, 2014, 04:51:56 PM
OK.  Then I'll add that task to my to-do list if no one else offers to.  Thanks anyways.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Mathi on January 24, 2014, 12:51:11 PM
Hi Rob,
   Mind if i try it.?
I was thinking of a script (perl) which can do this automatically.

-Mathi
Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 24, 2014, 02:40:28 PM
Absolutely, Mathi!  Thank you for the assist!  8)

Please create a directory named 'test' under the trunk/nasmx root directory and put as much code in there as you deem necessary.  You'll probably need to synchronize your svn first.  There's no rush since I'll be finalizing the struc/union macros within the next few days. 

I have other work remaining for this next release as well.  If you have anything else you'd like to check in then now is the time.  :D

Edit: Grammar.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 26, 2014, 04:38:34 AM
Progress!  Structure and union definitions ( including nested ) and natural size alignment are now fully implemented!
You can download the latest snapshot (http://sourceforge.net/p/nasmx/code/HEAD/tree/trunk/) to play with.

Nested unions containing nested structures/unions were causing me grief.  I spent the whole day rewriting the label offset algorithm due to the fact that, at macro instantion, there's no possible way to know the correct label offset if you're in a union because you don't yet know the alignment of future union members.

Consider the following structure definition as contained in WINSOCK.INC
Code: [Select]
NASMX_STRUC SOCKADDR_IN
    NASMX_RESERVE sin_family, int16_t, 1
    NASMX_RESERVE sin_port, uint16_t, 1
    NASMX_STRUC sin_addr, IN_ADDR
        NASMX_UNION S_un
            NASMX_STRUC S_un_b
                NASMX_RESERVE s_b1, uint8_t, 1
                NASMX_RESERVE s_b2, uint8_t, 1
                NASMX_RESERVE s_b3, uint8_t, 1
                NASMX_RESERVE s_b4, uint8_t, 1
            NASMX_ENDSTRUC
            NASMX_STRUC S_un_w
                NASMX_RESERVE s_w1, uint16_t, 1
                NASMX_RESERVE s_w2, uint16_t, 1
            NASMX_ENDSTRUC
    NASMX_RESERVE S_addr,   uint32_t, 1
        NASMX_ENDUNION
    NASMX_ENDSTRUC
    NASMX_RESERVE sin_zero, int8_t, 8
NASMX_ENDSTRUC

Yes, NASMX now portably and correctly supports those types of complex structure definitions.  8)

As you can see in the above structure, when the programmer specifies the union we cannot create offsets for the union members until after all members have been observed because at that point we do not know how large of an alignment we need yet.  That is the fallout of alignment.  Subsequently, the offset labeling now occurs in two phases using a form of iterative recursion.

Now that that's out of the way I'll begin working on providing packing and alignment macros to allow the programmer to override the default alignment requirements detected by NASMX during assembly.

Please let us know the results of any testing you do with NASMX regarding structures/unions here in this thread.
Thank you and happy testing!  :D
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 26, 2014, 10:36:50 AM
Progress!  Structure and union definitions ( including nested ) and natural size alignment are now fully implemented!

I stink think:

In this thread, i posted, some where above, file named: "win64_demo1.asm",
it show's that CREATESTRUCT_size variable is and was recognized.

But current test, on "Commit [r202]" (Latest snapshot), shows that something went\gone wrong,
OR at least, there is some, new "structure size" variable.

Just look, code file: "nasmx-code-202-trunk\demos\win64\DEMO1\demo1.asm", was updated to:
Code: [Select]
;// DEMO1.ASM
;//
;// Copyright (C)2005-2011 The NASMX Project
;//
;// This is a fully UNICODE aware, typedefined demo that demonstrates
;// using NASMX typedef system to make your code truly portable between
;// 32 and 64-bit systems using either ASCII or UNICODE
;//
;// Contributors:
;//    Bryant Keller
;//    Rob Neff
;//
%include 'windemos.inc'

entry    demo1

[section .code]

proc   demo1, ptrdiff_t argcount, ptrdiff_t cmdline
locals none

    ; CREATESTRUCT
    ; -----------------------------------------------------------------------------------
    invoke wsprintfA,buffer,txt_number,txt_CREATESTRUCT,CREATESTRUCT.lpCreateParams
    invoke wsprintfA,buffer,txt_number,txt_CREATESTRUCT,CREATESTRUCT_size
    invoke wsprintfA,buffer,txt_number,txt_CREATESTRUCT,CREATESTRUCT_Size
    invoke wsprintfA,buffer,txt_number,txt_CREATESTRUCT,CREATESTRUCT_SIZE
    invoke MessageBoxA, NULL, buffer, NULL, MB_OK
    invoke ExitProcess, NULL

endproc

[section .data]
    buffer: times 250 db 0
    txt_number:  declare(NASMX_TCHAR) NASMX_TEXT('%s, %d'), 0x0
    txt_CREATESTRUCT:  declare(NASMX_TCHAR) NASMX_TEXT('CREATESTRUCT'), 0x0

NASMX_STRUC CREATESTRUCT
    NASMX_RESERVE lpCreateParams, ptrdiff_t, 1
    NASMX_RESERVE hInstance,  ptrdiff_t, 1
    NASMX_RESERVE hMenu,      ptrdiff_t, 1
    NASMX_RESERVE hWndParent, ptrdiff_t, 1
    NASMX_RESERVE cy,         int32_t, 1
    NASMX_RESERVE cx,         int32_t, 1
    NASMX_RESERVE y,          int32_t, 1
    NASMX_RESERVE x,          int32_t, 1
    NASMX_RESERVE style,      int32_t, 1
    NASMX_RESERVE lpszName,   ptrdiff_t, 1
    NASMX_RESERVE lpszClass,  ptrdiff_t, 1
    NASMX_RESERVE ExStyle,    int32_t, 1
NASMX_ENDSTRUC

AND,
It produces, compile output:
Code: [Select]
DEMO1.asm:25: error: symbol `CREATESTRUCT_size' undefined
DEMO1.asm:26: error: symbol `CREATESTRUCT_Size' undefined
DEMO1.asm:27: error: symbol `CREATESTRUCT_SIZE' undefined

Usage of variable "CREATESTRUCT.lpCreateParams", proves, that CREATESTRUCT is defined.
So, i tried at least three common possible "struct size" variable definitions and none of them was\were recognized.

Might be caused by...
OLD code, nasmx.inc, NASMX_STRUCT, here we could define CREATESTRUCT_size (%$__nx_size):
Code: [Select]
        ....
        ;// create new ctx and initialize
%push %3
%xdefine %$__nx_name %%__tname
%assign %$__nx_size %%__tsize
        ...
NEW code, nasmx.inc, NASMX_STRUCT, here is no such thing (%$__nx_size):
Code: [Select]
        ...
        ;// create new ctx and initialize
%push %3
%xdefine %$__nx_name %%__tname
%define %$__nx_isnested %%__is_nested
        ...

So, i got no clue, how to get "structure size".

Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 26, 2014, 03:22:57 PM
Ahh, the difference between nasm's %define and equ!

Compare this small snippet:
Code: [Select]
    mov eax, CREATESTRUCT_size
    %define CREATESTRUCT_size 48

which generates 'error: symbol `CREATESTRUCT_size' undefined'

to this:
Code: [Select]
    mov eax, CREATESTRUCT_size
    CREATESTRUCT_size equ 48

which assembles correctly.

CREATESTRUCT_size should probably be an equate.  But in the current revision it was %define'd.  You brought that to light since you placed the definition of the CREATESTRUCT in the data segment rather than at the top of the file in an include-like fashion.  Subsequently, the use of the CREATESTRUCT_size was unknown at the point you attempted to invoke.  So I'll fix that for sure.

A nice feature to add would be a sizeof() operator.  One is used internally in NASMX but with extreme caution.
Consider a structure member offset - CREATESTRUCT.lpCreateParams - which is an offset of zero (0) from the beginning of the structure.  It gets equated to zero and becomes unmodifiable at that point.  Regardless of whether it is defined or equated we can't simply do a sizeof(CREATESTRUCT.lpCreateParams) in order to find the size of that member variable.  It would be the same as calling sizeof(0)!  That's why nasm, and subsequently NASMX, append _size to the structure names and members before any equating occurs.  It's sort of like a reversed C sizeof() macro.
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 26, 2014, 03:43:40 PM
Ahh, the difference between nasm's %define and equ!

Ahh, yes. :D
Okay, okay, now it's clear, now it's works.

A nice feature to add would be a sizeof() operator.

Yes, it would eliminate, the need of typing/appending with "_size".
But, now, it's possible to live with out this operator.
That sizeof(X) operator could be like a new feature, in case, it get's verified and is not needed to be use with caution.

EDIT0:

Hey, look at this:
Code: [Select]
;// DEMO1.ASM
;//
;// Copyright (C)2005-2011 The NASMX Project
;//
;// This is a fully UNICODE aware, typedefined demo that demonstrates
;// using NASMX typedef system to make your code truly portable between
;// 32 and 64-bit systems using either ASCII or UNICODE
;//
;// Contributors:
;//    Bryant Keller
;//    Rob Neff
;//
%include 'windemos.inc'

entry    demo1

[section .code]

proc   demo1, ptrdiff_t argcount, ptrdiff_t cmdline
locals none

   
    ; SOCKADDR_IN
    ; -----------------------------------------------------------------------------------
invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_family
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_port
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_addr
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_addr.S_un
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_addr.S_un.S_addr
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_addr.S_un.S_un_b
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_addr.S_un.S_un_w
    invoke wsprintfA,buffer,txt_format_offset,buffer,SOCKADDR_IN_TEST.sin_zero
    invoke MessageBoxA, NULL, buffer, NULL, MB_OK

endproc

[section .data]
    buffer: times 250 db 0
    txt_format_offset: db '%s',13,10,'offset: %d', 0x0
    txt_format_init:  declare(NASMX_TCHAR) NASMX_TEXT('%s, %d'), 0x0
    txt_CREATESTRUCT:  declare(NASMX_TCHAR) NASMX_TEXT('CREATESTRUCT'), 0x0



NASMX_STRUC SOCKADDR_IN_TEST
    NASMX_RESERVE sin_family, int16_t, 1
    NASMX_RESERVE sin_port, uint16_t, 1
    NASMX_STRUC sin_addr, IN_ADDR
        NASMX_UNION S_un
            NASMX_STRUC S_un_b
                NASMX_RESERVE s_b1, uint8_t, 1
                NASMX_RESERVE s_b2, uint8_t, 1
                NASMX_RESERVE s_b3, uint8_t, 1
                NASMX_RESERVE s_b4, uint8_t, 1
            NASMX_ENDSTRUC
            NASMX_STRUC S_un_w
                NASMX_RESERVE s_w1, uint16_t, 1
                NASMX_RESERVE s_w2, uint16_t, 1
            NASMX_ENDSTRUC
    NASMX_RESERVE S_addr,   uint32_t, 1
        NASMX_ENDUNION
    NASMX_ENDSTRUC
    NASMX_RESERVE sin_zero, int8_t, 8
NASMX_ENDSTRUC

Output is a message box:
Code: [Select]
offset: 0
offset: 2
offset: 4
offset: 4
offset: 4
offset: 4
offset: 4
offset: 8


Subsequently, the use of the CREATESTRUCT_size was unknown at the point you attempted to invoke.

Here is difference, define vs equ :
1. Structure member offsets is\are know at the time they are invoked.
2. But structure size is not.

So I'll fix that for sure.

Okay.

I think the "fix" will be:
back to definition with EQU
OR
requirement, that structures must have to be defined before programmer access them.




Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 26, 2014, 04:34:06 PM
We could make it work but with a required syntax change.

Let's use the following definition as an example:
Code: [Select]
NASMX_STRUC POINT
    NASMX_RESERVE x, uint16_t, 1
    NASMX_RESERVE y, uint16_t, 1
NASMX_ENDSTRUC

Let's create two macros:
Code: [Select]
    %define sizeof(x) ( x %+ _size )
    %define offsetf(x) ( x %+ _offset )

The key to this even working properly is that we now, instead of:
Code: [Select]
    mov eax, dword [ pt + POINT.y ];
    mov ecx, POINT.y_size

we now must use those macros as follows:
Code: [Select]
    mov eax, dword [ pt + offset( POINT.y ) ]
    mov ecx, sizeof( POINT.y )

The structure member names ( such as POINT.y ) would have to no longer be equated when creating structure definitions.  Instead, we would create an equate named POINT.y_offset.  Unfortunately, this is even more typing, but even worse is that the consequence of changing this would break any existing code terribly.  :'(

Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 26, 2014, 05:41:13 PM
Unfortunately, this is even more typing, but even worse is that the consequence of changing this would break any existing code terribly.

I agree, more typing would not be good, and also break existing codes would be catastrophe. :)

Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 26, 2014, 07:17:22 PM
Well, that's why compilers and assemblers have pragmas and command line switches, right?  ;)

We can either extend the syntax which is only enabled if switched on (thus the programmer WANTS to use it), otherwise we keep the existing.

I'm wondering what other C-style compiler functionality we can add in since it's only worth doing if we gain a quite a few new features and capabilities.  We'll have to ponder on that ...
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 26, 2014, 07:45:24 PM
Well, that's why compilers and assemblers have pragmas and command line switches, right?  ;)

We can either extend the syntax which is only enabled if switched on (thus the programmer WANTS to use it), otherwise we keep the existing.

Yes, you are right!
But command line switch implementation requires
a new official source code release of NASM itself, so, others could use it,
while things for NASMX can be managed just only in a single NASMX.INC file.

The thing i wanted to say, is, that - command line switches might take a little bit more time to implement.

I'm wondering what other C-style compiler functionality we can add

compiler functionality

I read, somewhere, in the past and could partly agree, someone said, it would be nice: C / C++ style comments.
Well it doesn't matter for me, i'm satisfied with current ';' - comments.


I'm wondering what other C-style compiler functionality we can add

It might end up having a NASM compiler which fully supports C. :D



Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 26, 2014, 08:26:20 PM
But command line switch implementation requires a new official source code release of NASM itself

No, I wouldn't even think of asking the nasm devs to put in a switch.  I'd use either the existing nasm -d command line switch, eg: -d NASMX_NEW_STUFF, since nasm would define that for us or make it a NASMX_PRAGMA that can be set only once.
For example, to use NASMX on FreeBSD, you have to define -d FREEBSD in order to assemble on that platform properly.

I read, somewhere, in the past and could partly agree, someone said, it would be nice: C / C++ style comments.

Unfortunately, the nasm token sequence of '//' is already used for signed division.  That immediately rules out that style of comment.

It might end up having a NASM compiler which fully supports C. :D

LOL! I'm pretty sure that the nasm devs do NOT want to go down that rabbit hole! :D
Title: Re: Win64 Structure Alignment (Win API)
Post by: Rob Neff on January 27, 2014, 02:00:19 AM
More progress!  Added pragma pack!  Let's download the snapshot (http://sourceforge.net/p/nasmx/code/HEAD/tree/trunk/) and check it out.

Here is sample code you can play with:
Code: [Select]

%define __NX_DEBUG_STRUC
%include 'nasmx.inc'

; Usage:
;     NASMX_PRAGMA PACK, PUSH, value
;           where value is either 1 or a small power of 2 ( eg: 2,4,8,16,32 )

NASMX_PRAGMA PACK, PUSH, 1

NASMX_STRUC PACKTEST
NASMX_RESERVE w,       uint16_t, 1
NASMX_RESERVE width,   uint32_t, 1
NASMX_RESERVE height,  uint32_t, 1
NASMX_RESERVE c,       uint8_t, 1
NASMX_RESERVE x,       uint16_t, 1
NASMX_ENDSTRUC

; restore natural alignment
NASMX_PRAGMA PACK, POP


Notice the line %define __NX_DEBUG_STRUC at the top.  That will be removed before release but currently allows you to see the output generated by the parser.  It's definitely enlightening to study.  Play around with different packing sizes to see the adjustments occur.  To see what would normally be generated without packing simply comment out the pragma lines.

Enjoy.  ;D

ps: struc sizes are now back to being equated once again.
Title: Re: Win64 Structure Alignment (Win API)
Post by: Bryant Keller on January 27, 2014, 03:25:09 AM
I read, somewhere, in the past and could partly agree, someone said, it would be nice: C / C++ style comments.

If you have a copy of the GNU C/C++ compiler, you _can_ have C/C++ comments in your NASM code. Here is an example:

Code: (demo.asm) [Select]
/**
 * Filename: demo.asm
 * Developer: S. Bryant Keller <bkeller@about.me>
 * Created: 26 Jan 2014 10:25 PM
 * Reason: To show encryptor256 how to use C/C++ comments in
 * NASM source.
 * Build: cpp demo.asm -o demo.temp
 * nasm -f elf demo.temp -o demo.o
 * gcc demo.o -o demo
 */

BITS 32

GLOBAL main
EXTERN printf

%define NewLine 10

SECTION .text

main: ; (int argc, char **argv) :int {{{
%define main.argc (ebp + 8)
%define main.argv (ebp + 12)
enter 0, 0
mov eax, [main.argv]
mov eax, [eax] ;; eax := argv[0]

push eax
push sMyNameIs
call printf
add esp, (4 * 2)

xor eax, eax ;; return (0)
leave
ret
;}}}

SECTION .data

sMyNameIs: db "This program is called: %s", NewLine, 0

;  vim: set fdm=marker ft=nasm ts=4 sw=4 tw=0 noet :
Title: Re: Win64 Structure Alignment (Win API)
Post by: encryptor256 on January 27, 2014, 10:29:50 AM
More progress!  Added pragma pack!

Okay, i will check this out.
I have never, ever used "packing" practically. :D

If you have a copy of the GNU C/C++ compiler, you _can_ have C/C++ comments in your NASM code. Here is an example

Thanks for example, this is something new, didn't knew that it's, even possible, here is win64 example:
Code: [Select]
/**
 * Filename: demo.asm
 * Developer: S. Bryant Keller <bkeller@about.me>
 * Created: 26 Jan 2014 10:25 PM
 * Reason: To show encryptor256 how to use C/C++ comments in
 * NASM source.
 * Build: cpp demo.asm -o demo.temp
 * nasm -f elf demo.temp -o demo.o
 * gcc demo.o -o demo
 */
/*
 * Original demo was modified to fit 64 bits.
 * Filename: (unchanged)
 * Translator: J.K. Encryptor256
 * Translated: 27 Jan 2014 12:09 PM
 * Reason: To say thanks and provide with Win64 example,
 * because didn't managed to run or compile 32 bit version correctly on Win64.
 * Build: cpp de... (unchanged)
 * nasm -f win64 demo.temp -o demo.o
 * gcc de... (unchanged)
*/

BITS 64

GLOBAL main
EXTERN printf

SECTION .text

align 16
main:
; Save all default arguments
mov [rsp+8*1],rcx
mov [rsp+8*2],rdx
mov [rsp+8*3],r8
mov [rsp+8*4],r9

; Define something
%define main.argc (rbp+8*2)
%define main.argv (rbp+8*3)

; Create stack
push rbp
mov rbp,rsp
lea rsp,[rsp-8*4]

; Print
; - assign RDX -> [[main.argv]] : Program name
; - assign R8 -> [[main.argv+8]] : First argument
mov rax,[main.argv]
mov r8,[rax+8]
mov rdx,[rax]
mov rcx,txt_format_arguments
call printf

; Clear stack n quit
lea rsp,[rsp+8*4]
pop rbp
ret

SECTION .data

txt_format_arguments: db "This program name is '%s' and is called by '%s'!",0


So, when i run, using command line: "demo.exe Computer", it gives\prints result:
Code: [Select]
This program name is 'demo.exe' and is called by 'Computer'!