Author Topic: Extending struc/istruc  (Read 25119 times)

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Extending struc/istruc
« on: August 16, 2010, 04:00:27 PM »
Built in support for nested structures and unions (named and/or unnamed).
The following is a rather simple example:

Code: [Select]
struc MSG
  .hwnd    resq 1         ; MSG.hwnd equ 0, MSG.hwnd_size equ 8
  .message resd 1         ; MSG.message equ 8 , MSG.message_size equ 4
  .wParam  resq 1         ; MSG.wParam equ 12 , MSG.message_size equ 8
  .lParam  resq 1         ; MSG.wParam equ 20 , MSG.message_size equ 8
  .u union                ; MSG.u equ 28  ( named union )
    .time    resd 1       ; MSG.u.time equ 28, MSG.u.time_size equ 4
    struc                 ; unnamed nested struc
      .time_l  resw 1     ; MSG.u.time_l equ 28, MSG.u.time_l_size equ 2
      .time_h  resw 1     ; MSG.u.time_h equ 30, MSG.u.time_h_size equ 2
    ends                  ; no size can be defined for unnamed struc or union
  endu                    ; MSG.u_size equ 4
  .pt struc               ; MSG.pt equ 32 ( named nested struc )
    .x resd 1             ; MSG.pt.x equ 32 , MSG.pt.x_size equ 4
    .y resd 1             ; MSG.pt.y equ 36 , MSG.pt.y_size equ 4
  ends                    ; MSG.pt_size equ 4
ends                      ; MSG_size equ 40

istruc MSG, message       ; create label for message address
  at MSG.hwnd   dq 0       
  at MSG.u.time dd 0x0100 ;
  at MSG.pt.x   dd 64
iends                     ;

I have successfully implemented something similar within NASMX using macros, but - IMHO, this additional syntax support really belongs in Nasm proper. The syntax provides transparency such that it doesn't break pre-existing code and would provide multiple benefits as compared to the current implementation.

Klod

  • Guest
Re: Extending struc/istruc
« Reply #1 on: October 06, 2010, 04:55:28 AM »
Hi Rob, I agree one hundred percent.
The NAsm struc/istruc mechanism is one area of Nasm that I have a hard time warming up to. For a while I used the old xstruc/ixstruc macros by Joergen Ibsen. But still... I had a look at the latest NASMX implementation to. I decided to try my hand at an implementation for two reasons: 1. to test the preprocessor in revision and secondly to test my "know how" of Nasm/preprocessor.
The following example is heavily influenced by Bryant Kellers OOP example. It is by no means complete, nesting needs to implemented  and also init t,test_one,< etc> needs to be complete. For the time being, I decided to use the syntax t.test_one.z, (including the strucname) in the definition. This was done mainly for my sake of learning how to compose symbols for later reuse.

Code: [Select]
%imacro STRUCT 1-2 0
%push __STRUCT__
%define %$context __STRUCT__
%define %$name %1
%assign %$nItems 0
%assign %$size %2
%assign %$oset %2
[ABSOLUTE %2]
%{$name}:
%endm

%imacro UNION 1-2 0
%push __UNION__
%define %$context __UNION__
%define %$name %1
%assign %$nItems 0
%assign %$base %2
%assign %$max 0
[ABSOLUTE %{$base}]
%{$name}:
%endm

%imacro ENDS 1
%ifn (%{$name} <> %1)
    %ifctx __UNION__
    %assign %{$name}_size    %$max
    %assign %{$name}_noitems %{$nItems}
    %define _UNION_%{$name}_defined %{$name}
    %warning "number_of_items"  %$nItems  %{$name}'_size' %$max  '_UNION_'%[%{$name}]_defined _UNION_%{$name}_defined  %$context
    %pop
    %elifctx __STRUCT__
    %assign %{$name}_size    %$size
    %assign %{$name}_noitems %{$nItems}
    %define _STRUCT_%{$name}_defined %{$name}
    %warning  "number_of_items" %{$name}_noitems  %{$name}'_size' %$size '_STRUCT_'%[%{$name}]_defined _STRUCT_%{$name}_defined %$context
    %pop
    %else
    %define __SECT__ [SECTION .data]
    %endif
    %ifdef __SECT__
    __SECT__
    %endif   
%else
    %error we are in the wrong context
%endif
%endm

%imacro SET 1-3
%ifctx __STRUCT__
    %assign %$nItems %$nItems +1
    %xdefine %[%{$name}]_item_%[%{$nItems}]_iname  .%{1}
    %xdefine %[%{$name}]_item_%[%{$nItems}]_ofset %{$oset}
    %{$name}%+.%1 equ  %$oset
    %define %[%{$name}]_item_%[%{$nItems}]_size %2
    %assign %$size %$size+%2
    %warning %[%{$name}]_item_%[%{$nItems}]'_size' %2 'and  ofset' %{$name}_item_%[%{$nItems}]_ofset 'and ' %[%{$name}]_item_%[%{$nItems}]_
    %assign %$oset %$size
%elifctx __UNION__
    %assign %$nItems %$nItems +1
    [ABSOLUTE %{$base}]
    . %+ %1:
    %xdefine %[%{$name}]_item_%[%{$nItems}]_size %2
    %xdefine %[%{$name}]_item_%[%{$nItems}]_iname .%+ %{1}
    %if %$max < %2
    %assign %$max %2
    %warning %[%{$name}]_item_%[%{$nItems}] size %$max  %[%{$name}]_item_%[%{$nItems}]_
    %endif
   
%endif
%endm

%macro init 1-3+
%push __INITIALIZE__
%define %$context __ISTRUCT__
%define %$tag %1
%define %$sname %2
    %ifdef _STRUCT_%{$sname}_defined
        %ifidni %{3}, <>
                [Section .data]
                align 4
                 %$tag:  times %{$sname}_size db 0
                 %assign %$nItems 1
                 %rep %{$sname}_noitems
                     %{$tag}%+.%{$sname}%+%[%{$sname}]_item_%[%{$nItems}]_iname    equ  %{$tag}+%{$sname}_item_%{$nItems}_ofset   
                     %warning %{$tag}%+.%{$sname}%+%[%{$sname}]_item_%[%{$nItems}]_iname      %{$tag}+%{$sname}_item_%{$nItems}_ofset
                     %assign %$nItems %$nItems+1               
                 %endrep
                 __SECT__
        %else
            %warning %2 is not an empty struct, handle argument initializing
        %endif       
    %elifdef _UNION_%{2}_defined
        %ifidni %{3}, <>
                [Section .data]
                align 4
                 %{$tag}:  times %{2}_size db 0
                %assign %$nItems 1
                 %rep %{$sname}_noitems
                     %{$tag}%+.%{$sname}%+%[%{$sname}]_item_%[%{$nItems}]_iname    equ  %{$tag}+%{$sname}_item_%{$nItems}_size   
                     %warning %{$tag}%+.%{$sname}%+%[%{$sname}]_item_%[%{$nItems}]_iname      %{$tag}+%{$sname}_item_%{$nItems}_size
                     %assign %$nItems %$nItems+1               
                 %endrep
                 __SECT__       
        %else
            %warning else clause%2
        %endif   
    %else
        %ERROR %2 not defined
    %endif
%pop
%endm

struct test_one
    set x,4
    set y,2
    set z,16
ends test_one

UNION union_one
    set a,1
    set b,2
    set c,4
    set d,8
ENDS union_one


    EXTERN GetStdHandle
    EXTERN GetConsoleMode
    Extern SetConsoleTitleA
    EXTERN WriteFile
    EXTERN SetConsoleMode
    EXTERN WaitForSingleObject
    EXTERN ReadFile
    Extern wsprintfA
   
[Section .data]
    msg    DB    'Press any key to continue...',13,10
    .len
    conTitle    db     "Test--- Struct testing ---tseT",0   
    strFmt    DB    `[t.test_one.x]: %d\n[t.test_one.y]: %d\n[t.test_one.z]: %d\ntest_one_size: %d\nt.test_one.x: %d\nt.test_one.y: \
 %d\nt.test_one.z: %d\n[union_one.c]: %d\nunion_one_size: %d\n`,0
    strBuf    TIMES 1025 DB 0
   


[Section .bss]
    hStdIn    RESD 1
    hStdOut    resd 1
    hBuffer        RESD 1
    hNum        RESD 1
    hMode        RESD 1


[Section .text]
Start:

init t,test_one,<>
;init p,test_two,<>            ;ERROR, test_two is not defined
init q,union_one,<>
    push -11
    call GetStdHandle
    mov [hStdOut],eax
    push -10
    call GetStdHandle
    mov     dword[hStdIn], eax
   
    push dword[hStdIn]
    push dword hMode
    call GetConsoleMode
   
    push conTitle
    call SetConsoleTitleA
   
   
    mov dword[q.union_one.c],0xfffffff
    push dword union_one_size
    push dword[q.union_one.c]
   
    mov dword [t.test_one.x], 0x1
    mov word [t.test_one.y], 0xfff
    mov dword [t.test_one.z], 0x3

    mov dword [t.test_one.z], 0x3
    mov dword [t.test_one.z+4], 0x4
   
    push t.test_one.z
    push t.test_one.y
    push t.test_one.x
    Push dword test_one_size
    Push dword [t.test_one.z]
    xor eax,eax
    mov ax,word [t.test_one.y]
    push eax
    ;Push word [t.test_one.y]            ;don't work stack misaligned
    Push dword [t.test_one.x]
    Push DWORD strFmt
    Push DWORD strBuf
    Call wsprintfA
    Add Esp, (9*4)    ;c style function
   
    push 0
    push dword hNum
    push  DWORD 1024
    push DWORD strBuf
    push dword[hStdOut]
    call WriteFile

   
    push 0
    push dword hNum
    push  DWORD msg.len-msg
    push DWORD msg
    push dword[hStdOut]
    call    WriteFile

    push 0
    push DWORD hNum
    push dword 1
    push DWORD hBuffer
    push dword[hStdIn]
    call ReadFile
    push 0
    EXTERN ExitProcess
    call ExitProcess


This example will compile with nasm -f and link with goasm

Regards,
Klod

Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: Extending struc/istruc
« Reply #2 on: October 06, 2010, 12:12:52 PM »
I have successfully implemented something similar within NASMX using macros, but - IMHO, this additional syntax support really belongs in Nasm proper.

NASMX's nested union or struc macro must be used in a different way than in your example, as there is currently no way to determine the label in front of a macro. Therefore, you're right in that this exact syntax would belong into NASM (the assembler or the preprocessor itself), because it currently can't be implemented by macros.

Quote
[...] would provide multiple benefits as compared to the current implementation.

Over all, it would make unions more readable. It can be implemented by macros, except for labels preceding the nested union or struc macro to name the nested union or struc.
C. Masloch

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Extending struc/istruc
« Reply #3 on: October 06, 2010, 01:53:12 PM »
Over all, it would make unions more readable. It can be implemented by macros, except for labels preceding the nested union or struc macro to name the nested union or struc.

Actually, when I originally wrote the NASMX struc macros I was unaware of an undocumented preprocessor feature %00 which does in fact provide access to the label preceeding the macro - provided said label appears on the same line during invocation of the macro.  This feature is now being documented (along with a possible %: alias - Keith could better answer that).  I "might" revisit this syntax for the next release to provide more consistency with nasm's istruc.

Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: Extending struc/istruc
« Reply #4 on: October 06, 2010, 02:59:00 PM »
Ok.. so basically the syntax you proposed can be done with macros now (or so I would think). This could go into NASM's default macros, or it could be made available in a %use package. "Built-in support" sounds like you want to code it into the source, which isn't necessary for this.

Wait actually there is an issue: %00 or %: can be used to access the label, but it probably can't be re-defined this way. (Its definition can't be avoided.) This provides some obstacles for such struc and union macros and would likely result in the creation of unnecessary labels.
« Last Edit: October 06, 2010, 03:03:00 PM by cm »
C. Masloch

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Extending struc/istruc
« Reply #5 on: October 06, 2010, 04:38:33 PM »
Ok.. so basically the syntax you proposed can be done with macros now (or so I would think). This could go into NASM's default macros, or it could be made available in a %use package. "Built-in support" sounds like you want to code it into the source, which isn't necessary for this.

The main reason for my proposal of including nested structs/unions directly into nasm source was two-fold:
1) To make nasm itself more programmer friendly such that macros wouldn't be needed to enable this capability if already built in;
2) Compilation speed.
As an example: currently, %include windows.inc brings the preprocessor to a crawl as most Windows structures have been defined within that one file.  Not making all those macro calls (at least 4 per struc) and associated defines/equates would reduce compile time considerably. Another avenue of increasing speed is splitting out all those defines and structure definitions into a format more familiar with the SDK as separate header/include files.  This is a monumental task but eventually doable.  I've begun work on a program to help with converting SDK headers to nasm includes - h2incn ( a similar name/project previously attempted by another developer) but have been rather pre-occupied with other NASMX issues lately.  If you're interested in helping with header conversions PM me - I'll glady accept any help I can get ;)

Offline nasm32

  • Jr. Member
  • *
  • Posts: 25
Re: Extending struc/istruc
« Reply #6 on: September 09, 2014, 10:14:52 PM »
[120 Day BUMP, mov eax, dword [Sorry_About_That]]

I absolutely agree that a full blown struc, union should be implemented into nasm. It is cruicial. Let me explain why in few points:

1a. Implementing these basic things with the help of nasm macros is misuse of the macro system
1b. It is misuse because the amount of macroinstructions it takes, absolutely overloads the macro system
1c. If implemented directly into nasm, would produce perhaps a quarter of that (Much easier in code)

2. People should be using the extremely fine macro system inside nasm for other purposes than writing basic elements like structures.

3. The basic rule of any macro system. If it takes too much to macro'it, put it in code.