Assembly

来自osdev
跳到导航 跳到搜索

到计算机的核心内部,发送到机器任何部分的每个信号都是一系列电脉冲。 如果电脉冲高,例如5伏,表示发送二进制1位。 如果电脉冲低,例如0伏,表示发送二进制0位。 把4个二进制数字放在一起,你会得到一个半字节(nibble)。 把8个放在一起,你会得到一个字节(byte)。 把16个放在一起,你会得到一个字(word)。 计算机理解这些部分中的命令,但人类可很难理解。 所以人们开发了一种更好的查看此类信息的方式,那就是使用十六进制。 通常不需要16个位就可以显示一个命令,记住以下命令变得更加方便:(译者注:原文这里好像有些错误,应该主要这里是指的机器码)

90 - No Operation
CC - Break
E9 - 16 bit jump
CD - Interrupt
等。

但是很快,人们了解到这种代码需要用户友好,因此发明了汇编代码。 使用汇编代码,你可以用更易于人类阅读的特殊代码表示计算机操作。 例如JMP 跳转、INT 中断、NOP 空操作等。

汇编程序是读取汇编文件 (通常使用扩展名.asm) 并将其转换为二进制可执行文件的程序。 这非常类似于生成可执行程序的编译器。 但是,汇编程序与编译器的不同之处在于,编译器隐藏了系统的底层细节,而汇编程序则向你暴露了这些细节。

为任何汇编器编写的源代码定义为 “汇编语言。“但这并不意味着什么,因为在完全相同的平台上,每个汇编器可能需要用于完全相同的程序的不同源代码。

汇编语法

在汇编中,每个指令 (或操作/运算符/操作码) 后面都有一个逗号分隔的参数 (或操作数) 列表。 这些操作数可以是立即值 (即数字,如1,2, 十六进制0x16,0101二进制符号 b),或寄存器registers,或内存memory位置。 例如,

mov eax, 123

这里指令是mov,操作数是eax和123。这里eax是寄存器,123是立即值。

汇编有两个主要的语法: 英特尔语法和AT&T语法。

Intel语法

一般来说,一个运算的第一个操作数是目标操作数,另一个操作数 (或多个操作数) 是源操作数。 例如:

mov eax, 123

mov指令从源操作数获取一个值,并将其放置在目标操作数中,因此该值123将被放置到寄存器eax中。 最初的Intel语法是Intel ASM386汇编程序的语法 (后来也授权给最终已经消失了的RadiSys)。 从那时起,许多汇编程序发明了它的许多变体。 此外,它在大多数在线汇编教程中被使用,因为这些教程中的大多数是在 TASM (使用的是Intel语法) 占主导地位的汇编程序时编写的。

AT&T语法

AT&T语法与Intel语法相反。 操作的数据是从左向右传送。 以下是与上述AT&T语法相同的语句。

mov $123, %eax

还有一些其他与操作数的区别:

  • 诸如123之类的字面值以 “$” 为前缀 (请参见上面的示例)。
  • 内存位置没有前缀: mov 123, %eax 将存储在123的值移动到eax。
  • 寄存器以 “%” 为前缀
  • 当使用寄存器作为指针时,将其放在括号中: mov (%eax), %ebx将存储在eax中的指针处的值移动到ebx。
  • 当使用带有内存位置的语句 (没有寄存器存在) 时,指令后需要后缀。 例如: movl $123, 123. 需要'l' (代表长整形),告诉汇编器值为32位。
  • 指针可以通过前缀常量来偏移:4(%eax) 指向4+%eax。
  • 指针可以通过将它们写为 :(%eax,%ebx) 来偏移另一个寄存器,指向 x x
  • 最后,如果需要,您可以将其全部组合: 4(%eax,%ebx,2) 将为4+%eax+%ebx*2

另见

文章

外部链接

de:Assembler