NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: lfa on January 31, 2011, 05:58:53 PM

Title: NASM numeric equates (or: problems with %assign)
Post by: lfa on January 31, 2011, 05:58:53 PM
Hi all,

I'm trying to figure out a way of achieving the following (MASM snippet) in NASM:

Code: [Select]
link = 0
; ...
  dd link
  link = $
; ...

where the assignment of $ to link will be evaluated multiple times and employed in the construction of a linked list.

I initially thought that I could use %assign for this purpose, but read in the manual that

The expression passed to %assign is a critical expression (see section 3.8 ), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

Any ideas on how I might go about solving this in NASM?

Thanks in advance.
Title: Re: NASM numeric equates (or: problems with %assign)
Post by: cm on January 31, 2011, 07:04:36 PM
There are several ways to solve that, but I would probably do it like this:

Code: [Select]
%define link 0     ; or %assign, doesn't matter in this case
; ...
%define link construct
; ...

This assumes that your code really contains a label like "construct" each time that you want to re-define link. So, a second re-definition would have to look somewhat like this (as labels must be unique, you cannot re-use the label "construct"):

Code: [Select]
%define link second_construct
; ...

It might require less typing or be easier to implement in your code to use macro-local labels ( or context-local labels ( For example, using macros along the former:

Code: [Select]
%define link 0
 %macro constructlabel 0
%define link %%construct
; ...
; ...
; ...

Notice how the macro is used multiple times, but in fact defines a different label each time. "link" is re-defined (in the preprocessor) to the last defined label's name. If you use a macro to create your constructs (the "; ..." parts) anyway, then you could include the two lines in my example's macro at the beginning of your macro instead of using two separate macros.

This mechanism could be implemented using context-local labels instead.
Title: Re: NASM numeric equates (or: problems with %assign)
Post by: lfa on January 31, 2011, 09:21:33 PM
Thanks for your suggestions cm; here's what I've ended up with:

Code: [Select]
%define link 0

%macro update_link 0
  dd link
  %define link %%update_link

Nice and compact.
Title: Re: NASM numeric equates (or: problems with %assign)
Post by: Bryant Keller on February 03, 2011, 07:28:15 AM
Not quite, the masm code is using 'link = $' to set link to the address after the dd, so what you are actually creating is something like:

Code: (LinkedList.asm) [Select]
CPU 386

%macro StartList 1

%macro addNode 1+
dd %[%%addr]

%macro EndList 0

%macro for_each 1
%push _FOR_EACH_
    mov edi, %{1}
    mov eax, [edi]
    or eax, eax
    jz %[%$end_of_for]
    push edi
    mov eax, [edi+4]

%macro end_for 0
    pop edi
    mov edi, [edi]
    jmp %[%$start_of_for]


StartList myList
    addNode DD 1
    addNode DD 7
    addNode DD 5
    addNode DD 8
    addNode DD 12
    addNode DD 32

strFmt DB "%d", 10

EXTERN printf

GLOBAL _start

for_each myList

    push eax
    push strFmt
    call printf ; display it
    add esp, 8


    xor eax, eax
    xor ebx, ebx
    inc eax
    int 80h

The code which scans the linked list is Linux/GlibC dependent, but the macros should work on any platform.

Code: (console) [Select]
[bkeller@localhost ~/temp] $ nasm -f elf -o LinkedList.o LinkedList.asm
[bkeller@localhost ~/temp] $ gcc -nostartfiles LinkedList.o -o LinkedList
[bkeller@localhost ~/temp] $ ./LinkedList
[bkeller@localhost ~/temp] $

WARNING: Not a whole lot of thought was put into this example, it's by no means meant to be optimized (in fact, for_each is down-right ugly).  But at least it works!  ;D

Bryant Keller
Title: Re: NASM numeric equates (or: problems with %assign)
Post by: lfa on February 03, 2011, 12:06:42 PM
Thanks for the suggestion Bryant.

I should have clarified that the caller has been reworked to point at the dword containing the link address rather than the following cell; this makes walking the list simpler (and creating the list in .text very straightforward with the update_link macro).