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.
%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