NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: 440bx on February 03, 2011, 03:34:08 PM

Title: How to get the size of a variable ?
Post by: 440bx on February 03, 2011, 03:34:08 PM
Hello,

I'm looking for some directive in NASM that will yield the size of a variable.  For instance, presume that I have defined:

BytesWritten  dd 0

and in the code section I want to push the size of "BytesWritten". Something along the lines of:

push  sizeof BytesWritten   ; <---- I cannot find how to do this using NASM
push  somethingelse
call    Afunction

currently I am hardcoding the size of the operand to the push but, I would really rather not do that.

I've looked everywhere, manual, sample programs, google but have not found the answer.   Your help is much appreciated,

Thank you.

Title: Re: How to get the size of a variable ?
Post by: cm on February 03, 2011, 05:23:00 PM
Technical answer: NASM does not store any type information with labels; to NASM, a label simply is a reference to some address. The concept of a "variable" is not built into NASM. Therefore, you have to figure out yourself what size your "variables" have.

More useful answer: Since NASM does not do any type specification stuff, you either have to keep hard-coding your variables' size (in the case of a dword, 4), or write some macros that can be used similar to the "sizeof" directive of other assemblers in your code as you demonstrated. For example:

Code: [Select]
%macro dwordvar 1-2 0
; Define the label (parameter %1):
%1:
; Reserve the space and write the initial value (parameter %2, defaults to zero):
 dd %2
; Define the label "%1_size", ie the variable's name followed by "_size", as the size
%1_size equ 4
 %endmacro

; This appends "_size" to the specified label name
%define sizeof(name) name%+_size

You could then,

Code: [Select]
dwordvar BytesWritten

; ...

push sizeof(BytesWritten)

and you could create multi-line macros similar to my "dwordvar" example to create word or byte sized variables, too.
Title: Re: How to get the size of a variable ?
Post by: 440bx on February 03, 2011, 05:49:19 PM
Technical answer: NASM does not store any type information with labels; to NASM,

Christian,

Thank you very much.  I keep forgetting the fact that type information is not kept by NASM.  The macro you suggested will do perfectly.

I appreciate your help, thanks again.
Title: Re: How to get the size of a variable ?
Post by: Frank Kotler on February 03, 2011, 09:30:55 PM
More often used to determine the length of a string...

Code: [Select]
byteswritten dd 0
sizeof_byteswritten equ $ - byteswritten

... should work also...

Best,
Frank

Title: Re: How to get the size of a variable ?
Post by: Bryant Keller on February 04, 2011, 01:34:17 AM
Basically the same answer as cm, but uses a more generic set of macros.

Code: [Select]
%idefine TWORD_size 10
%idefine QWORD_size 8
%idefine DWORD_size 4
%idefine WORD_size 2
%idefine BYTE_size 1
%imacro VAR 2+
%{1}: %{2}
%{1}_size equ ($-%{1})
%endmacro
%idefine sizeof(_x_) _x_%+_size
;...
[SECTION .data]
var strMessage, DB "Hello World!", 0
var ptrMessage, DD strMessage
;...
[SECTION .bss]
var strBuffer, RESB 1024
;...
mov eax, sizeof(strMessage)
mov ebx, sizeof(ptrMessage)
mov ecx, sizeof(strBuffer)
mov edx, sizeof(dword)

I like this method and use it myself quite a lot, especially when dealing with the Linux system-call functions. For example:

Code: [Select]
[SECTION .data]
var strMessage, DB "Hello, World!"
;...
mov edx, sizeof(strMessage)
mov ecx, strMessage
mov ebx, FILENO_STDOUT
mov eax, SYS_write
int 0x80

Seems a bit more readable to me. In fact, I tend to add VAR and SIZEOF into the standard macros file so my personal build of NASM has these fixed in by default, just have to move the file over on each build.
Title: Re: How to get the size of a variable ?
Post by: cm on February 04, 2011, 01:56:27 PM
Here's a small change in the way the labels are named (now prefixed instead of suffixed) and the single-line macro "sizeof" is defined:

Code: [Select]
%idefine sizeof_TWORD 10
%idefine sizeof_QWORD 8
%idefine sizeof_DWORD 4
%idefine sizeof_WORD 2
%idefine sizeof_BYTE 1
%imacro VAR 2+
%{1}: %{2}
sizeof_%{1} equ ($-%{1})
%endmacro
%idefine sizeof sizeof_%+

This is to change the syntax of our "sizeof" keyword to be compatible with that of some other assemblers, as seen in the initial post, if you prefer it that way:

Code: [Select]
mov ecx, sizeof strBuffer
mov edx, sizeof dword

Code: [Select]
push  sizeof BytesWritten
Title: Re: How to get the size of a variable ?
Post by: Bryant Keller on February 04, 2011, 10:38:22 PM
I prefer the use of postfix instead of prefix, since STRUC/ENDSTRUC generates the %{1}_size  symbol for structures created in NASM.. although you could rewrite the internal STRUC macros to provide the prefix version also..
Title: Re: How to get the size of a variable ?
Post by: 440bx on February 05, 2011, 01:45:21 AM
Christian, Frank, Bryant,

Thank you very much for all the suggestions.   Great stuff !  I'm slowly getting the "NASM way"  ;)

Much appreciated.