mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-09-22 10:43:39 -04:00
FR 2499968: structures with non-zero base offset
Add an optional second argument to struc, document it and test it. Also removed trailing whitespace in nasmdoc.src in the process.
This commit is contained in:
@@ -3742,13 +3742,15 @@ structures; instead, the preprocessor is sufficiently powerful that
|
||||
data structures can be implemented as a set of macros. The macros
|
||||
\c{STRUC} and \c{ENDSTRUC} are used to define a structure data type.
|
||||
|
||||
\c{STRUC} takes one parameter, which is the name of the data type.
|
||||
This name is defined as a symbol with the value zero, and also has
|
||||
the suffix \c{_size} appended to it and is then defined as an
|
||||
\c{EQU} giving the size of the structure. Once \c{STRUC} has been
|
||||
issued, you are defining the structure, and should define fields
|
||||
using the \c{RESB} family of pseudo-instructions, and then invoke
|
||||
\c{ENDSTRUC} to finish the definition.
|
||||
\c{STRUC} takes one or two parameters. The first parameter is the name
|
||||
of the data type. The second, optional parameter is the base offset of
|
||||
the structure. The name of the data type is defined as a symbol with
|
||||
the value of the base offset, and the name of the data type with the
|
||||
suffix \c{_size} appended to it is defined as an \c{EQU} giving the
|
||||
size of the structure. Once \c{STRUC} has been issued, you are
|
||||
defining the structure, and should define fields using the \c{RESB}
|
||||
family of pseudo-instructions, and then invoke \c{ENDSTRUC} to finish
|
||||
the definition.
|
||||
|
||||
For example, to define a structure called \c{mytype} containing a
|
||||
longword, a word, a byte and a string of bytes, you might code
|
||||
@@ -3767,8 +3769,8 @@ from the beginning of a \c{mytype} structure to the longword field),
|
||||
\c{mt_word} as 4, \c{mt_byte} as 6, \c{mt_str} as 7, \c{mytype_size}
|
||||
as 39, and \c{mytype} itself as zero.
|
||||
|
||||
The reason why the structure type name is defined at zero is a side
|
||||
effect of allowing structures to work with the local label
|
||||
The reason why the structure type name is defined at zero by default
|
||||
is a side effect of allowing structures to work with the local label
|
||||
mechanism: if your structure members tend to have the same names in
|
||||
more than one structure, you can define the above structure like this:
|
||||
|
||||
@@ -3792,6 +3794,26 @@ so code such as \c{mov ax,[mystruc.mt_word]} is not valid.
|
||||
correct syntax is \c{mov ax,[mystruc+mt_word]} or \c{mov
|
||||
ax,[mystruc+mytype.word]}.
|
||||
|
||||
Sometimes you only have the address of the structure displaced by an
|
||||
offset. For example, consider this standard stack frame setup:
|
||||
|
||||
\c push ebp
|
||||
\c mov ebp, esp
|
||||
\c sub esp, 40
|
||||
|
||||
In this case, you could access an element by subtracting the offset:
|
||||
|
||||
\c mov [ebp - 40 + mytype.word], ax
|
||||
|
||||
However, if you do not want to repeat this offset, you can use -40 as
|
||||
a base offset:
|
||||
|
||||
\c struc mytype, -40
|
||||
|
||||
And access an element this way:
|
||||
|
||||
\c mov [ebp + mytype.word], ax
|
||||
|
||||
|
||||
\S{istruc} \i\c{ISTRUC}, \i\c{AT} and \i\c{IEND}: Declaring
|
||||
\i{Instances of Structures}
|
||||
|
@@ -39,14 +39,14 @@
|
||||
__SECT__
|
||||
%endmacro
|
||||
|
||||
%imacro struc 1.nolist
|
||||
%imacro struc 1-2.nolist 0
|
||||
%push
|
||||
%define %$strucname %1
|
||||
[absolute 0]
|
||||
[absolute %2]
|
||||
%$strucname: ; allow definition of `.member' to work sanely
|
||||
%endmacro
|
||||
%imacro endstruc 0.nolist
|
||||
%{$strucname}_size:
|
||||
%{$strucname}_size equ ($-%$strucname)
|
||||
%pop
|
||||
__SECT__
|
||||
%endmacro
|
||||
@@ -57,7 +57,7 @@ __SECT__
|
||||
%$strucstart:
|
||||
%endmacro
|
||||
%imacro at 1-2+.nolist
|
||||
times %1-($-%$strucstart) db 0
|
||||
times (%1-%$strucname)-($-%$strucstart) db 0
|
||||
%2
|
||||
%endmacro
|
||||
%imacro iend 0.nolist
|
||||
|
33
test/struc.asm
Normal file
33
test/struc.asm
Normal file
@@ -0,0 +1,33 @@
|
||||
;Testname=test; Arguments=-fbin -ostruc.bin; Files=stdout stderr struc.bin
|
||||
|
||||
bits 32
|
||||
|
||||
; Simple struc example
|
||||
struc teststruc1
|
||||
.long: resd 1
|
||||
.word: resw 1
|
||||
.byte: resb 1
|
||||
.str: resb 32
|
||||
endstruc
|
||||
|
||||
; Reference with offset
|
||||
mov [ebp - 40 + teststruc1.word], ax
|
||||
|
||||
istruc teststruc1
|
||||
at .word, db 5
|
||||
iend
|
||||
|
||||
; Struc with base offset
|
||||
; should be the same as the previous stuc
|
||||
struc teststruc2, -40
|
||||
.long: resd 1
|
||||
.word: resw 1
|
||||
.byte: resb 1
|
||||
.str: resb 32
|
||||
endstruc
|
||||
|
||||
mov [ebp + teststruc2.word], ax
|
||||
|
||||
istruc teststruc2
|
||||
at .word, db 5
|
||||
iend
|
Reference in New Issue
Block a user