汇编语言8086 EQU指令

6

我在汇编(8086)中,对于EQU指令的含义感到困惑。

abc EQU xyz

EQU 是否会在代码中找到 abc 时直接将其与 xyz 进行交换,无论 xyz 表示什么,例如数值等等?

也就是说,我可以这样写吗?

varA EQU [bp+4]

mov ax, varA

还有一个问题是,EQU是否可以全局访问?也就是说,我可以在过程之外定义EQU,并在过程中使用它吗?


取决于您使用的实际汇编器。是emu8086吗?那我不知道。但大多数x86汇编器没有预处理器。因此,在这种情况下,EQU在定义时进行评估,而不是替换。我99%确定这也是您的情况。如需预处理器,请随意运行一些C编译器预处理器(甚至可以是独立的东西,但我始终有gcc,所以我会选择C)。 - Ped7g
嗯,我明白了。汇编语言中有像预处理器这样的东西吗?我可能需要它吗? - luka032
刚刚编辑了我的答案,以证明EQUs是全局的(在过程内声明的EQU)。 - Jose Manuel Abarca Rodríguez
3个回答

11

EQU指令并不是变量,它们不占用任何内存空间:

  • EQU指向一个常量值时,它就成为该值的同义词。即使您尝试更改它,该值也无法被覆盖。
  • EQU指向另一个变量时,它就成为该变量的同义词,因此发生在同义词上的所有操作都将发生在变量上。

将下面的代码复制粘贴到EMU8086中并运行:

.model small
.stack 100h
.data

xyz DW  2016    ;◄■■■ ABC IS NOT A VARIABLE, IT IS
abc EQU xyz     ;     JUST A SYNONYM FOR XYZ.

pqr EQU 10      ;◄■■■ PQR IS NOT A VARIABLE, IT IS
                ;     JUST A SNYNONYM FOR NUMBER 10.

varA EQU [bp+2] ;◄■■■ BP POINTS TO GARBAGE.

.code

mov  ax, @data
mov  ds, ax

mov  abc, 25    ;◄■■■ XYZ BECOMES 25!!!!

mov  pqr, 999   ;◄■■■ NO ERROR, BUT THE VALUE WILL NOT CHANGE.
mov  ax, pqr    ;◄■■■ AX IS NOT 999, AX=10.

mov  si, varA   ;◄■■■ GARBAGE.
mov  bp, sp
mov  si, varA   ;◄■■■ DIFFERENT GARBAGE.
push ax         ;◄■■■ PUSH 10.
call my_proc

mov  ax, NUMBER ;◄■■■ YES, EQUS ARE GLOBAL!!! (AX=0B9H).

mov  ax, 4c00h
int  21h

;-----------------------------------------

my_proc proc  
mov  bp, sp
mov  si, varA    ;◄■■■ WRONG VALUE (ANOTHER GARBAGE). 
mov  si, [bp+2]  ;◄■■■ PROPER VALUE (10).

varB EQU [bp+2]
mov  si, varB    ;◄■■■ WRONG AGAIN.

NUMBER EQU 0b9h  ;◄■■■ DEFINE EQU INSIDE PROCEDURE.

ret
my_proc endp          

[bp+2]的情况下,它似乎并不起作用,可能是因为编译器无法获得固定值。


3
使用varA EQU [bp+2]varB EQU [bp+2]产生的垃圾清晰地表明EMU8086本不应该在第一时间接受这些等式。又发现了模拟器中的另一个缺陷!+1 很高兴看到你花时间了解EQU。 - Fifoernik

4
EQU表示相等,因此abc EQU xyz,xyz必须先定义好。

在你的第二个例子中,需要这样写:
%define varA [bp+4]

mov   ax, varA

当您的代码被组装后,对象转储将产生以下结果:

mov ax, [bp+4]

然后您可以执行类似以下操作:

Bubble equ varA

mov  bx, Bubble

并且您将得到

mov bx,[bp + 4]

通常,所有汇编器的工作方式都相同,尽管在语法上有微妙的差别,例如NASM需要使用% ,而其他汇编器可能不需要。


3
有些汇编器具有合理的宏支持,通常作为预处理器内部工作或非常接近预处理器。
否则,如我在评论中所写,为什么不使用C预处理器?(它是一个独立的工具,您可以使用它预处理任何文本文件,只需使用#define和其他扩展您的asm源代码,其余内容不必看起来像C源代码,预处理器不关心,它正在处理文件作为[任何]文本文件)。
你需要吗?我不需要。我只因缺乏经验而在ASM中编写了大量代码,而宏/预处理器不会拯救我免于那个巨大的错误(它们可能只会使它不那么明显,并且在更长时间内变得更加可忍受)。
虽然您仅出于教育目的或性能/低级别事项在ASM中编写小代码片段,但宏/预处理器将IMHO添加一层抽象,阴影下生成的指令,因此在调试期间,您可能会发现自己问“这个从哪里来?”我更喜欢手写每个ASM指令,知道我为什么要把它放在那里,我不想在ASM代码中有任何意外,已经相当难以编写无错代码在ASM中。
再说一遍,我在ASM中的大部分晚期工作都是256B介绍,所以我确实需要了解每个字节的产生方式... :)

我敢打赌你就是那个写了只有256字节的Apple ][扩展卡ROM的家伙。它们的内存非常紧凑,我看到一些代码跳转到另一个指令的中间以获得副作用。这是另一个分支指令的偏移量0x38,后面跟着RTS。那个0x38恰好是指令SEC,那个厚颜无耻的家伙跳到那里以带进位标志的方式获取RTS - Weather Vane
@WeatherVane 我必须谦虚地承认我从来没有做到那一步……自修改代码?有。将代码本身也用作处理数据?有。但是部分重复使用操作码……我不记得我做过这个。这是一个有趣的轶事,谢谢。:) (我从来没有玩过 Apple ][,只有 ZX Spectrum) - Ped7g

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接