3

我正在尝试使用 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.

But labelis a word where [label]is a byte。为什么我的编译器不能区分这些?

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,这是不可接受的。但我觉得他们在语言中是允许的。

4

3 回答 3

5

我怀疑你想要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.
于 2012-06-08T01:53:43.573 回答
4

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

您可以使用指令offsetdw等明确地告诉 A86 您希望它做什么,因此它不必进行猜测。

A86手册说明:“重要提示:你必须了解标签和变量之间的区别,因为如果你混淆它们,你可能会生成与你预期不同的指令。例如,如果你声明 XXX: DW ?,那么 XXX 后面的冒号表示 XXX 是标签;指令 MOV SI,XXX 将 XXX 的立即常数地址移动到 SI 寄存器中。另一方面,如果您声明 XXX DW ? 不带冒号,则 XXX 是字变量;同样的指令 MOV SI,XXX现在做了一些不同的事情:它将内存字 XXX 的运行时值加载到 SI 寄存器中。您可以使用立即值运算符 OFFSET 或内存变量运算符 B,W 覆盖任何用法中的符号定义, D、Q 或 T。因此,无论 XXX 是如何声明的,MOV SI,OFFSET XXX 都会加载指向 XXX 的立即数;MOV SI,无论 XXX 是如何声明的,XXX W 都会在 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
于 2020-03-28T18:27:36.043 回答
1

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

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

以BBBB为基础

也是对段的基数的引用 - 推送 cx 后相同 [我想 - 我不记得了]

与上述相同,除了 BBBB 是 SSSS 用于分段

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

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

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

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

于 2014-12-17T18:13:21.063 回答