【问题标题】:When do I need to specify the size of the operand in Assembly?什么时候需要在 Assembly 中指定操作数的大小?
【发布时间】:2020-10-12 20:22:20
【问题描述】:

我刚开始在大学学习汇编(x86,NASM),我对它的工作原理感到非常困惑。在我有很多关于它的问题中,这一直困扰着我。

什么时候需要指定操作数的大小?有规律吗?例如:

segment  data use32 class=data
    a  db 10
    b  dw 40
segment  code use32 class=code
start:
    mov  AX, [b]
    div  BYTE [a]

这里我们将div操作码中操作数的大小指定为BYTE。如果我删除 BYTE 部分,我会收到一个错误,所以我们需要指定它。

segment  data use32 class=data
    a  db 10
    b  dw 40
segment  code use32 class=code
start:
    mov  AH, 2
    mul  AH

在这里,我们不需要指定操作数2 的大小。它只是工作。

那么我什么时候必须指定尺寸?是不是很简单:当我在内存中声明了一个变量时,指定它的大小?考虑到上面给出的例子,我倾向于这样认为,但通过我对 Assembly 的短暂体验,我发现它往往会违背我的逻辑来判断事情应该如何工作。

另外,在告诉我何时需要指定尺寸之后,您能否也告诉我为什么我们需要这样做?当我们需要这样做时,我们为什么需要这样做?我的意思是,我们已经声明了变量,所以变量的类型应该对程序可见,不是吗?为什么要指定大小,否则会报错?

【问题讨论】:

  • 对汇编器来说,你实际上并没有声明一个变量,你已经定义了一个符号。汇编器不知道也不关心您正在使用该符号来访问该符号所指位置的变量。 NASM 符号没有类型,这是一个有意的设计决定,将它与 MASM 区分开来,MASM 确实提供了符号类型。
  • 几乎重复:Why do we need to disambiguate when adding an immediate value to a value at a memory address 暗示当没有寄存器操作数,只有寻址模式和/或立即数时需要它。
  • @RossRidge 您能否解释一下符号和变量之间的确切区别(至少对汇编程序而言)是什么?这两件事有什么作用?
  • 内存变量是在程序的数据部分中保留的一个、两个或多个字节。 Symbol是你给这个变量起的名字,代表这个内存变量第一个字节的地址。

标签: assembly x86 nasm


【解决方案1】:

如果可以从您指定的其他内容中推断出操作数大小,则无需指定操作数大小。比如mov只对两个大小相同的操作数起作用,而AX是一个字长的寄存器,所以在mov AX, [b]中,可以推断出[b]一定是字长的。但是你只为div指定了一个操作数,所以你必须告诉它[a]的大小,因为它没有任何信息可以从中推断出来。

【讨论】:

  • 用常量加法怎么样?为什么我可以在不指定任何内容的情况下向寄存器添加像 2 这样的值?
  • @user010517720 您可以通过这种方式将 2 添加到寄存器,因为寄存器始终具有固定大小(例如,eax 始终是双字)。
  • 那么它会自动将 2 视为 dword 吗?因为eax 是双字?
  • @user010517720 对。
猜你喜欢
  • 2020-08-10
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
相关资源
最近更新 更多