我正在尝试使用 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,这是不可接受的。但我觉得他们在语言中是允许的。
我怀疑你想要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.
您遇到的问题源于A86是单通道汇编器的事实。当您在定义它们之前使用testz
和second
等符号时,A86必须猜测它们是什么。它假设它们将是即时值,但后来发现它们实际上是标签。多阶段汇编器可能会返回并更改它之前做出的决定,但 A86 不会这样做。它只是发出一个错误(#16)。这就是为什么错误出现在定义附近的源文件中的原因:这就是 A86 发现问题时的位置。
您可以使用指令 offset
、d
、w
等来明确告诉 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 覆盖任何用法中符号的定义。因此,MOV SI,OFFSET XXX 加载指向 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
DOS手册指示处理程序的指针:
mov ax, word ptr es:[bx],bbbb
BBBB是基础的地方
也是对段基础的引用-推CX后相同[我想-我不记得了]
除BBBB外,与上述相同是SSSS用于隔离
现在,当我的鼠标由于严重崩溃而停止运行时,我编写了一个处理程序,我将这个单词ptr用作字节而不是单词,它似乎可以工作,因为我从未制作过实际的单词指针,而只是在程序中使用"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 不被羊膜,直到计算请求或命令请求完全完成,除非它是作为 IRQ 请求执行的,它可能会被 sti 和 cli 挂起,中间是更改页表或引用表的参考。