以下是在Kip Irvine的汇编语言x86书中找到的汇编程序链接列表。在main中,循环遍历列表并显示所有节点值。程序没有在循环中使用固定的计数器,而是在尾节点中检查空指针,并在找到后停止循环。我的问题如下:

(a)有人可以解释吗?它是如何工作的,它是什么意思?

(b)有人可以解释(ListNode PTR [esi])。NextPtr吗?那是什么意思?

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

最佳答案

有人可以解释(ListNode PTR [esi]).NextPtr吗?那是什么意思?

这意味着在ListNode寄存器中有一个指向ESI结构开始的指针。它取消引用该指针,并求值为NextPtr字段。
基本上就像您在C中具有以下内容:

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


有人可以解释< Counter, ($ + Counter * SIZEOF ListNode) >吗?它是如何工作的,它是什么意思?

不,老实说我不能。好吧,对不起,这真是一个糟糕的答案。 :-)
不过,我可以告诉您如何解决。首先,我要去the documentation for MASM,看看是否可以发现任何看起来相关的东西。我会发现(或者,实际上,我已经知道)$表示the current value of the location counter,而SIZEOFan operator that returns the number of bytes in the specified type
因此,该混搭看起来像是将Counter的值乘以ListNode结构的大小,然后将位置计数器的当前值相加。
但是我仍然不知道尖括号的含义。因此,我尝试使用Google搜索,例如“尖括号MASM”。我得到this question,它不是很有用,因为它没有答案。在MASM32帮助文件中,我看到:

视为单个文字字符串。尖括号通常用于宏调用中,并与FOR指令一起使用,以确保将参数列表中的值视为单个参数。 。 。每次将参数插入宏扩展时,汇编器都会删除一组尖括号。

但这对我也没有太大帮助。
然后去哪儿?好吧,假设代码可以正常工作,我将其汇编并要求MASM生成列表文件(/Fl)。然后,我将检查该清单文件,以查看其实际上对生成的代码产生了什么影响。
更新:我的奉献得到了回报,我遇到了an old manual for MASM 6.1 online。我无法在Microsoft的在线文档中找到它,但是在本手册中,它在pg上明确指出。 98:

定义结构和联合变量
声明结构或联合类型后,即可定义该类型的变量。对于定义的每个变量,将以类型声明的格式在当前段中分配内存。定义结构或联合变量的语法为:
[[name]] typename < [[initializer [[,initializer]]...]] >
[[name]] typename { [[initializer [[,initializer]]...]] }
[[name]] typename constant DUP ({ [[initializer [[,initializer]]...]] })

名称是分配给变量的标签。如果不提供名称,则汇编器会为变量分配空间,但不会给它提供符号名称。 typename是先前声明的结构或联合类型的名称。
您可以为每个字段指定一个初始化程序。每个初始化程序的类型必须与类型声明中定义的字段相对应。对于联合,初始化程序的类型必须与第一个字段的类型相同。初始化列表也可以使用DUP运算符。

因此,它看起来像这样声明了一个ListNode类型的未命名变量,并且括号中的内容是ListNode结构的初始化程序,有点像C代码:
struct ListNode { ... } = { Counter, ($ + Counter * sizeof(ListNode)) };

这与试图做出解释性评论的微不足道的尝试相吻合:

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


因为它使用这些值初始化ListNode结构的前两个字段NodeDataNextPtr

10-08 18:45