【问题标题】:A86 - definition conflicts with forward referenceA86 - 定义与前向引用冲突
【发布时间】:2012-06-12 02:49:38
【问题描述】:

我正在尝试使用 A86 为 8086 组装一些代码。我将问题缩小到 4 行代码。

MOV BX, testz
ADD AL, [testz]

INT 20h
testz:
~     ^
#ERROR 16: Definition Conflicts With Forward Reference                    @@@@#
db ?

您认为这段代码有什么问题?我将地址本身移动到 BX 寄存器并将 testz 地址中的字节值添加到 AL。

在一个更大的程序中,我还得到了#ERROR 13: Byte/Word Combination Not Allowed

但是label 是一个字,而[label] 是一个字节。为什么我的编译器不能区分这些?

ADD BL, [second]
MOV BX, second
~             ^
#ERROR 13: Byte/Word Combination Not Allowed   
second:
~      ^
#ERROR 16: Definition Conflicts With Forward Reference                    @@@@#
db ?

因为我看不到任何字节/字冲突。


我的编译器平等地解释偏移量 testz 和 testz。 我查看了字节码,没有发现任何区别。

MOV BX, testz
ADD AL, [BX]

上面的代码有效,但是有没有其他方法可以让我在一行中做到这一点

ADD AL, [testz]

每当我在 [] 中添加标签名称时,根据我的编译器 a86,这是不可接受的。但我觉得他们在语言中是允许的。

【问题讨论】:

    标签: assembly x86-16 forward-reference a86


    【解决方案1】:

    我怀疑你想要MOV BX, offset testz。看来您的汇编程序将 [testz]testz 解释为相同的意思。

    您可以尝试使用名义上等效的 LEA BX, testz 来确认这一点

    编辑:(来自http://www.csn.ul.ie/~darkstar/assembler/manual/a14.txt):

    ERROR 16: Definition Conflicts With Forward Reference
    
       This error occurs when the assembler has previously guessed
       the type of a forward-referenced symbol in order to determine
       what kind of instruction to generate, and the guess turned out
       to be wrong.  The error is reported at the time the symbol is
       defined.  For example, when A86 sees MOV AX,FOO, it will
       assume FOO is an immediate value.  This error is reported if
       FOO turns out to be a word variable: FOO DW 0.  You need to
       search backwards from the error message, to references of FOO,
       and specify the type you intend to be used: MOV AX,FOO W.  If
       you really did intend to load the offset of FOO and not the
       memory contents, you can code MOV AX,OFFSET FOO to make the
       error message go away.
    

    【讨论】:

    • 啊!例如,这适用于 ADD AL,testz B。所以当我写 [testz] 时,我实际上是指 testz B。但是我的语法和假设是错误的吗?还是我的编译器选择以这种方式实现它们?
    • 已经……几十年了? ...自从我接触了A86。 8086 汇编器语法的事实标准是 MASM 的语法。但是 A86 做的事情有点不同。感觉就像 A86 正在尝试进行单通道组装,而 MASM 使用的是多通道方法。但我不记得了。
    【解决方案2】:

    DOS 手册为此类处理程序提供了指针:

    mov ax, word ptr es:[bx],BBBB

    以BBBB为基数

    也是对segment的base的引用-push cx后一样[我想-我记不清了]

    除BBBB外与上述相同的是SSSS用于分段

    现在我写了一个处理程序,当我的鼠标因严重崩溃而停止功能时,我使用这个词 ptr 作为一个字节而不是一个词,它似乎可以工作,因为我从未制作过实际的词指针,而只是使用了 'word ptr ' 在程序中以及将字节向后二进制转换为十六进制 [A6 向后是 65]。

    也是我在 int eh DOS amnual 中发现的错误,用于进行 INT 调用 [不像在调试程序集或 programmign 程序集中通过调用 int ## 但实际上直接调用 8080 并且事实是这样的这不是中断调用,而是 IRQ 调用。指令代码不正确——具体在演示文稿中。 同样在 Intel es:[bx] 上不起作用-必须使用 es[bx]

    还有扩展-我的头在哪里-回答您的问题,您要引用一个 8 位寄存器,然后是 16 位寄存器-您要指示 ADD bl,然后在添加操作数后更改 bx .这是你的错误 #13。

    您必须做的是确保 bl 在之前与 BX 兼容 - 否则您将得到一个无前向引用错误,这基本上是什么。ADD 指令自动保护 BX 不被放大,直到 tis 计算请求或命令请求是完全完成的,除非它是作为一个 IRQ 请求来执行的,它可能会被 sti 和 cli 挂起,中间是用于更改页表或引用表的引用。

    【讨论】:

      【解决方案3】:

      您遇到的问题源于 A86 是单通道汇编程序这一事实。当您在定义它们之前使用testzsecond 之类的符号时,A86 必须猜测它们是什么。它假设它们将是立即值,但后来它发现它们实际上是标签。多阶段汇编器可能会返回并更改其先前做出的决定,但 A86 不会这样做。它只是抛出一个错误(#16)。这就是错误出现在定义附近的源文件中的原因:这就是 A86 发现问题时所在的位置。

      您可以使用offsetdw 等指令明确地告诉 A86 你想让它做什么,这样它就不必猜测了。

      A86 manual 解释说:“重要提示:您必须了解标签和变量之间的区别,因为如果混淆它们,您可能会生成与预期不同的指令。例如,如果您声明 XXX : DW ?, XXX 后面的冒号表示 XXX 是一个标号;指令 MOV SI,XXX 将 XXX 的立即常数地址移动到 SI 寄存器中。 XXX 是一个字变量;同样的指令 MOV SI,XXX 现在做了一些不同的事情:它将内存字 XXX 的运行时值加载到 SI 寄存器中。您可以在任何用法中使用立即数覆盖符号的定义-值运算符 OFFSET 或内存变量运算符 B、W、D、Q 或 T。因此,无论 XXX 如何声明,MOV SI,OFFSET XXX 加载指向 XXX 的立即值;MOV SI,XXX W 加载字- XXX 处的变量,无论 XXX 是如何声明的。”

      这应该回答您的第二个问题:当 A86 看到 add bl, [second] 时,它假定 second 将是一个立即字节大小的操作数,因为 bl 是一个字节大小的寄存器。

      您的下一行 mov bx, second 期望 second 是立即字大小的操作数,但 A86 已经注意到 second 将是一个字节,因此您会收到错误 #13。

      你可以通过这样做得到你想要的:

      add bl, second b        ; add the byte at memory location ds:second to bl
      mov bx, offset second
      

      一般来说,如果您在使用符号之前定义它们,这些问题就会消失。例如,这将起作用:

      name example1 ; good code
      code segment
      org 0100h
      main:                   ; - MACHINE CODE
        mov bx, main          ; BB0001        - put 0100h in bx
        mov bx, offset main   ; BB0001        - put 0100h in bx
      ;         ^ offset directive not needed here
      ;           A86 already knows what to do
      
        mov bx, [main]        ; 8B1E0001      - put 00BBh in bx
      ;         ^ brackets work fine to dereference main here
      
        mov bx, main w        ; 8B1E0001      - put 00BBh in bx
      ;              ^ w does the same thing as brackets
      
      org 0150h
      goodbye:
        int 020h
      code ends
      end main
      

      但这不起作用:

      name example2 ; will not assemble
      code segment
      org 0100h
      main:                   ; - MACHINE CODE
        mov bx, goodbye       ; BB5001        - put 0150h in bx
      ;         ^ A86 assumes goodbye is an immediate value. This assumption
      ;           turns out to be a good one, so this line works OK
      
        mov bx, offset goodbye; BB5001        - put 0150h in bx
      ;         ^ offset directive tells A86 that goodbye will be an immediate
      ;           value. You can skip it, since A86 assumes that anyway
      
        mov bx, [goodbye] ; this line is the culprit!
      ;         ^ A86 doesn't know what to do about these brackets
      
        mov bx, goodbye w     ; 8B1E5001      - put 20CDh (`int 020h`) in bx
      ;                 ^ w directive tells A86 that goodbye will be a word 
      ;                   variable
      
      org 0150h
      goodbye:                ; label goodbye not defined until way down here!
        int 020h
      code ends
      end main
      

      【讨论】:

      • 所以A86基本上是所有可能世界中最差的,mov ax, label的含义取决于标签是代码还是数据标签?我认为 MASM 已经够糟糕了,其中“变量”神奇地暗示了操作数大小,而常量周围的[]sometimes ignored。但至少 MASM(我认为)一致认为裸标签始终是内存操作数,而不是立即数。 (另一方面,NASM 是一致的:裸符号 always 是立即数,[] 始终是内存操作数,您无需查看其他源代码行即可判断。)
      • 不管怎样,看看后来的汇编器从哪里得到他们的语法想法很有趣。
      • 关于SO的A86题多吗? A86 目前没有标签,但我们可以创建一个。 (具有高代表的用户可以创建标签并进行编辑,而无需经过审核队列,因此如果您知道更多链接,可以在评论中留下一些链接。)
      • @Peter-Cordes 是的,我回答这个问题的原因是,大约一周前,我一直在为同样的事情感到困惑——括号有时可以取消引用,但其他人则不行。我试着写下我希望当时能找到的答案。 :) 至于 A86 问题,在我完成我的 SO“方向”之后,SO 根据我选择的标签(x86 等)提出了一些我可能感兴趣的问题。其中一些是关于 A86 的,所以我搜索了“A86”并获得了大约 50 个点击。然而,其中一些是误报(很多是关于 Microsoft Excel 中的列...)
      • 我搜索并标记了几个问题;您可以删除那些链接 cmets。我创建了stackoverflow.com/tags/a86/info。您链接的一些问题以及其他提及 a86 的问题仅在答案中这样做,或者在问题中提及但不是关于 A86。
      猜你喜欢
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多