gordon sung
gordon sung

Reputation: 605

LinkedList in Assembly x86 Irvine

The following is a linked list Assembly program found in Kip Irvine's Assembly Language x86 book. In main, a loop traverses the list and displays all the node values. Rather than using a fixed counter for the loop, the program checks for the null pointer in the tail node and stops looping when it is found. My question is the following:

(a) Can someone explain < Counter, ($ + Counter * SIZEOF ListNode) >? How does it work and what does it mean?

(b) Can someone explain (ListNode PTR [esi]).NextPtr? What does that mean?

INCLUDE Irvine32.inc

    ListNode STRUCT
    NodeData DWORD ?
    NextPtr DWORD ?
    ListNode ENDS
    TotalNodeCount = 15
    NULL = 0
    Counter = 0

.data

    putc     macro   ptr

     push    eax

     mov     al, ptr
     call    writechar

     pop     eax
     endm

     ;to use:             
     ;putc        'a'



    LinkedList LABEL PTR ListNode

REPEAT TotalNodeCount
    Counter = Counter + 1
    ListNode <Counter, ($ + Counter * SIZEOF ListNode)>
    ;struct variables Counter, and ($+Counter*SIZEOF ListNode) being declared 
    ;
    ENDM

    ListNode <0,0> ; tail node

.code

main PROC
    mov esi,OFFSET LinkedList
    ; Display the integers in the NodeData fields.
    NextNode:
    ; Check for the tail node.

    putc    'a'; ->first node, then third node

    mov eax,(ListNode PTR [esi]).NextPtr
    cmp eax,NULL
    je quit
    ; Display the node data.

    putc   'b' ;->fourth node 

    mov eax,(ListNode PTR [esi]).NodeData
    call WriteDec
    call Crlf
    ; Get pointer to next node.

    putc   'c' ;->first node 
    putc   'd' ;->second node 
    mov esi,(ListNode PTR [esi]).NextPtr
    ;references a struct using [esi] 
    jmp NextNode
    quit:


    exit
main ENDP
END main

Upvotes: 3

Views: 4128

Answers (1)

Cody Gray
Cody Gray

Reputation: 244812

Can someone explain (ListNode PTR [esi]).NextPtr? What does that mean?

It means that there is a pointer to the beginning of a ListNode structure in the ESI register. It dereferences that pointer, and evaluates to the NextPtr field.

It is basically like if you had the following in C:

ListNode* esi;
...
return esi->NextPtr;

Can someone explain < Counter, ($ + Counter * SIZEOF ListNode) >? How does it work and what does it mean?

No, honestly I cannot. Well, sorry, this turned out to be a pretty crappy answer. :-)

I can tell you how I would figure it out, though. First I'd go to the documentation for MASM and see if I could spot anything that looked relevant. I would find (or, actually, I already know) that $ means the current value of the location counter, and that SIZEOF is an operator that returns the number of bytes in the specified type.

So this gobbledygook looks like it multiplies the value of Counter by the size of the ListNode structure, and then adds the current value of the location counter.

But I still have no idea what the angle brackets mean. So I'd try a Google search, something like "angle brackets MASM". I get this question, which isn't very useful, since it doesn't have an answer. In the MASM32 help file, I see:

Treats as a single literal string. Angle brackets are often used in macro calls and with the FOR directive to ensure that values in a parameter list are treated as a single parameter . . . The assembler removes one set of angle brackets each time it inserts an argument into a macro expansion.

but that doesn't really help me too much, either.

Where to go from here? Well, assuming that the code works, I'd assemble it and ask MASM to produce a listing file (/Fl). I would then inspect this listing file to see what effect this actually had on the generated code.

Update: My dedication paid off, and I came across an old manual for MASM 6.1 online. I wasn't able to find this in Microsoft's online documentation, but in this manual, it clearly says on pg. 98:

Defining Structure and Union Variables

Once you have declared a structure or union type, you can define variables of that type. For each variable defined, memory is allocated in the current segment in the format declared by the type. The syntax for defining a structure or union variable is:

[[name]] typename < [[initializer [[,initializer]]...]] >
[[name]] typename { [[initializer [[,initializer]]...]] }
[[name]] typename constant DUP ({ [[initializer [[,initializer]]...]] })

The name is the label assigned to the variable. If you do not provide a name, the assembler allocates space for the variable but does not give it a symbolic name. The typename is the name of a previously declared structure or union type.

You can give an initializer for each field. Each initializer must correspond in type with the field defined in the type declaration. For unions, the type of the initializer must be the same as the type for the first field. An initialization list can also use the DUP operator.

So it looks like this declares an unnamed variable of type ListNode, and the stuff in brackets is the initializer for the ListNode struct, sort of like the C code:

struct ListNode { ... } = { Counter, ($ + Counter * sizeof(ListNode)) };

That fits with the feeble attempt at an explanatory comment:

; struct variables Counter, and ($+Counter*SIZEOF ListNode) being declared

since it's initializing the first two fields of the ListNode struct, NodeData and NextPtr, with those values.

Upvotes: 2

Related Questions