Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

NASM does not have = and its %define does not work as I expected

13 views
Skip to first unread message

hcchen (gmail)

unread,
Dec 27, 2008, 6:26:47 AM12/27/08
to
NASM version 0.98.38 compiled on Sep 12 2003

I only want to make a linked strings like this, but it doesn't work as
I expeced

%define _link 0
xTable db 'abc',0
dw _link
%define _link $
db 'd',0
dw _link
%define _link $
db 'efghijk',0
lnkhead dw _link


1 %define _link 0
2
3 00000000 61626300 xTable db 'abc',0
4 00000004 0000 dw _link <=====
correct
5 %define _link $ <=== _link
is now = 6
6 00000006 6400 db 'd',0
7 00000008 [0800] dw _link <====
this should be 0006h but it's not !!
8 %define _link $ <=== _link
is now = A
9 0000000A 65666768696A6B00 db 'efghijk',0
10 00000012 [1200] lnkhead dw _link <===
this should be 000Ah but it's not !!


1

s_dubrovich

unread,
Dec 27, 2008, 1:52:51 PM12/27/08
to

Because of macro substitution, your code is really this:

%define _link 0
xTable db 'abc',0

dw $


%define _link $
db 'd',0

dw $


%define _link $
db 'efghijk',0

lnkhead dw $

For me, this is how I would do it:

1 ;; bits 16
2 [SECTION .text]
3 00000000 B8[0000] mov ax, xTable
4 00000003 BB[0600] mov bx, d
5 00000006 B9[0A00] mov cx, e
6
7
8 [SECTION .myTable vstart=0]
9
10 ;;
%define _link 0
11 00000000 61626300 xTable db 'abc',0
12 00000004 [0000] dw xTable ;;
_link
13 ;;
%define _link $
14 00000006 6400 d: db 'd',0
15 00000008 [0600] dw d ;;
_link
16 ;;
%define _link $
17 0000000A 65666768696A6B00 e: db 'efghijk',0
18 00000012 [0A00] lnkhead dw e ;;
_link

hth.

Steve

Frank Kotler

unread,
Dec 27, 2008, 6:37:55 PM12/27/08
to
hcchen (gmail) wrote:
> NASM version 0.98.38 compiled on Sep 12 2003

Valuable antique! :)

http://www.nasm.us

To be honest, I don't think a new version will help much...

As Steve points out, "$" is being evaluated where "_link" is used, not
where it's defined. "%define" is just kind of a text "cut and paste".

If you *could* get it to work... I don't see how you'd use it - you've
got a zero-terminated string, followed by... it's address, where I'd
expect "pointer to next". From the fact that you've got a 0 link after
"abc", and "lnkhead" associated with "efghijk", I'm guessing you want to
print 'em "backwards" - "efghijkdabc". Or... What *do* you intend?

Following the theory of "get something simple working first, then modify
it to do what you want", I've guessed "dos", and come up with this. I
followed Steve's lead and used "real labels" on the strings... but I
left out making a special section with vstart=0 - I don't think you need
that.

If this is anything like what you have in mind, we can work from there
to "automate" it a little (if that's what you want). If I'm nowhere near
close, straighten me out! :)

Best,
Frank

; nasm -f bin myfile.asm -o myfile.com
org 100h

section .data

xTable:
a: db 'abc',0
dw 0
d: db 'd',0
dw a
e: db 'efghijk',0
dw d

lnkhead dw e

section .text

mov si, [lnkhead]
call print_ll
ret

print_ll:
lodsb
cmp al, 0
jz .next
int 29h
jmp short print_ll
..next:
lodsw
test ax, ax
mov si, ax
jnz print_ll
ret

hcchen (gmail)

unread,
Dec 28, 2008, 3:31:11 AM12/28/08
to
Thank you and sorry for my unclear question. Here I make my question
clearer with a MASM actual code and .exe dump as shown below. This is
what I want ... a linked list of strings automatically linked by
assembler. As shown in the demo, SI always points to the recent string
and [si-2] points to the next string.
Microsoft MASM's = directive makes this very easy and beautiful. How
to do the same thing or any alternative by NASM ?

$STRING MACRO NAME,LABEL
DW _LINK
_LINK = $
LABEL DB NAME,0
ENDM

.model small mode
.code
entry: mov ax,_data
mov ds,ax
mov si,offset head ; si points to DS:1F 'head'
mov si,[si-2] ; si points to DS:14 'world !!'
mov si,[si-2] ; si points to DS:0c 'hello'
mov si,[si-2] ; si points to DS:06 'abc'
jmp $

.data
$STRING 'abc',abc
$STRING 'hello',hello
$STRING 'world !!',world
$STRING 'head',head

end entry

0B67:0000 FE EB FE 00 1F 00 61 62-63 00 06 00 68 65 6C
6C ......abc...hell
0B67:0010 6F 00 0C 00 77 6F 72 6C-64 20 21 21 00 14 00 68
o...world !!...h
0B67:0020 65 61 64 00 01 55 8B EC-A1 78 13 25 FF BF 81 66
ead..U...x.%...f

Frank Kotler

unread,
Dec 28, 2008, 2:41:21 PM12/28/08
to
hcchen (gmail) wrote:
> Thank you and sorry for my unclear question. Here I make my question
> clearer with a MASM actual code and .exe dump as shown below.

Great!

> This is
> what I want ... a linked list of strings automatically linked by
> assembler. As shown in the demo, SI always points to the recent string
> and [si-2] points to the next string.

Okay... I'd call it "previous string" - the "only" string we can link to
using this system (as far as I can see) - "previous" as written in the
source code. An "enhanced" version might let us do...

$STRING "Hello, ", hello, world

.... with the third parameter being "string to link to"...

> Microsoft MASM's = directive makes this very easy and beautiful. How
> to do the same thing or any alternative by NASM ?

This is a "quicky". I think we can do "better"(?). But I *think* this
does about the same as the Masm code. Can't link it (conveniently), but
the dump looks "about right". See if it helps any...

Best,
Frank


%macro $STRING 2
DW _LINK
%define _LINK %2
%2 DB %1,0
%endmacro

section code
...start:
mov ax,data
mov ds,ax
mov si, head ; si points to DS:1F 'head'


mov si,[si-2] ; si points to DS:14 'world !!'
mov si,[si-2] ; si points to DS:0c 'hello'
mov si,[si-2] ; si points to DS:06 'abc'
jmp $

section data
%define _LINK 0

Rod Pemberton

unread,
Dec 28, 2008, 7:07:09 PM12/28/08
to
"hcchen (gmail)" <spam...@crayne.org> wrote in message
news:264096dd-6ed3-43e4...@f40g2000pri.googlegroups.com...

I think you want %assign. I changed _link to lnk, but I believe _link
should work. You'll need $-$$ to get the offset from your org value...

bits 16

%assign lnk 0
xTable db 'abc',0
dw lnk
%assign lnk $-$$
db 'd',0
dw lnk
%assign lnk $-$$
db 'efghijk',0
lnkhead dw lnk


1 bits 16
2
3 %assign lnk 0
4 00000000 61626300 xTable db 'abc',0
5 00000004 0000 dw lnk
6 %assign lnk $-$$
7 00000006 6400 db 'd',0
8 00000008 0600 dw lnk
9 %assign lnk $-$$
10 0000000A 65666768696A6B00 db 'efghijk',0
11 00000012 0A00 lnkhead dw lnk


Rod Pemberton

hcchen (gmail)

unread,
Dec 31, 2008, 8:44:54 PM12/31/08
to
Ahhhh Yes, both work fine.
either

DW _LINK
%define _LINK %2
%2 DB %1,0

or

%assign lnk $-$$

It also works if I change to this
DW _LINK
%assign _LINK $-$$
DB %1,0
then it's totally same as MASM


DW _LINK
_LINK = $

DB NAME,0
Therefor, the equivalent form of "_LINK = $" in NASM is "%assign
_LINK $-$$"

I like it !!!

On 2008_$BG/_(B12_$B7n_(B29_$BF|_(B, _$B>e8a_(B8_$B;~_(B07_$BJ,_(B, "Rod Pemberton" <spamt...@crayne.org> wrote:
> "hcchen (gmail)" <spamt...@crayne.org> wrote in message

cac

unread,
Jan 7, 2009, 5:39:29 AM1/7/09
to
hcchen (gmail) wrote:
> Ahhhh Yes, both work fine.
> either
> DW _LINK
> %define _LINK %2
> %2 DB %1,0
>
> or
>
> %assign lnk $-$$

As I understand it, $-$$ resolves to the offset of the beginning of the
section, which may not be what you want. For my 32 bit flat memory
application, where I want addresses, not section offsets, the way I do
the link is:

%macro entry 1
%push entry
%$link:
db %1,0
dw %$$link
%endm

The "%push" creates a new context; the %$$link refers to the context one
below the top one on the stack. The contexts stack up and are never
popped, but my application has about 450 entries, and assembles with no
apparent problems.

-- Charles

H. Peter Anvin

unread,
Jan 8, 2009, 2:27:25 AM1/8/09
to
cac wrote:
>
> As I understand it, $-$$ resolves to the offset of the beginning of the
> section, which may not be what you want. For my 32 bit flat memory
> application, where I want addresses, not section offsets, the way I do
> the link is:
>
> %macro entry 1
> %push entry
> %$link:
> db %1,0
> dw %$$link
> %endm
>
> The "%push" creates a new context; the %$$link refers to the context one
> below the top one on the stack. The contexts stack up and are never
> popped, but my application has about 450 entries, and assembles with no
> apparent problems.
>

This is how I would do it [untested]:

%define __entry_prev 0
%define __entry_ctr 1
%macro entry 1
__entry_ %+ __entry_ctr :
db %1,0
dw __entry_prev
%xdefine __entry_prev __entry_ %+ __entry_ctr
%assign __entry_ctr __entry_ctr + 1
%endmacro

The contexts stacking up isn't really a huge problem, though, given the
memory sizes of modern workstations. Each context will eat something
like a few hundred bytes of memory.

-hpa

cac

unread,
Jan 8, 2009, 8:58:18 PM1/8/09
to
H. Peter Anvin wrote:

> The contexts stacking up isn't really a huge problem, though, given the
> memory sizes of modern workstations. Each context will eat something
> like a few hundred bytes of memory.

I was a bit concerned about that, but I wasn't able to get the kind of
solution you proposed working, so I went with the %push, which I did get
working.

My other concern had been build time; I spent a while in a tight
edit/build/test cycle, and became curious if my solution was "slow"; if
the %push, or the deep stack of pushes was consuming cpu. The code is
about 11,000 lines of assembly, with about 450 entries in the linked list:

assemble time with %push:

real 0m15.492s
user 0m14.838s
sys 0m0.030s

assemble time with macro math:

real 0m14.786s
user 0m14.135s
sys 0m0.028s


Hmmm.. your method is a bit faster. I'll probably switch my code over
because your solution seems less black-magicy; I'm using a side-effect
of %push, rather than your macro argument paste sleight-of-hand.
(I know mine is bad -- when I looked at it, I couldn't remember how it
worked and had to look in the nasm docs; a bad sign for readability.)

Thanks,
-- Charles

H. Peter Anvin

unread,
Jan 9, 2009, 12:30:55 AM1/9/09
to
cac wrote:
>
> I was a bit concerned about that, but I wasn't able to get the kind of
> solution you proposed working, so I went with the %push, which I did get
> working.
>
> My other concern had been build time; I spent a while in a tight
> edit/build/test cycle, and became curious if my solution was "slow"; if
> the %push, or the deep stack of pushes was consuming cpu. The code is
> about 11,000 lines of assembly, with about 450 entries in the linked list:
>
> assemble time with %push:
>
> real 0m15.492s
> user 0m14.838s
> sys 0m0.030s
>
> assemble time with macro math:
>
> real 0m14.786s
> user 0m14.135s
> sys 0m0.028s
>
>
> Hmmm.. your method is a bit faster. I'll probably switch my code over
> because your solution seems less black-magicy; I'm using a side-effect
> of %push, rather than your macro argument paste sleight-of-hand.
> (I know mine is bad -- when I looked at it, I couldn't remember how it
> worked and had to look in the nasm docs; a bad sign for readability.)
>

Is this code you could share? It seems a bit odd to me that 11,000
lines would take 15 seconds to assemble (perhaps I'm way too spoiled
with fast hardware...); I wouldn't mind running a profile on it.

-hpa

--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.

0 new messages