• 沒有找到結果。

本章目标

2.5  汇编语言

机器指令用0 和 1 模式来表示。这种模式在讨论或准备程序时是很不便的。因此,我们 使用符号名来表示这些模式。到目前为止,已经使用了自然单词如Load、Store、Add 以及 Branch 作为指令操作去表示相应的二进制码模式。当为一台指定的计算机编写程序时,这些 单词通常使用称为助记符(mnemonic)的缩写形式来代替,比如 LD、ST、ADD 和 BR。在识 别寄存器的时候,用简写符号也是很有用的,例如用R3 表示寄存器 3。最后,可能需要定义 像LOC 这样的符号来表示一个特定的存储单元。这些符号名以及使用规则的完整集合构成了 一种程序设计语言,通常叫做汇编语言(assembly language)。使用助记符以及描述完整的指令 和程序的规则集合称为这种语言的语法(syntax)。

使用汇编语言编写的程序可以被一个叫做汇编程序(assembler)的程序自动翻译成机器 指令的序列。这个汇编程序是实用程序集中的一个,它是计算机系统软件的一部分。汇编程序 与任何其他的程序一样,作为一个机器指令序列被存储在计算机的存储器中。一个用户程序通 常是通过键盘输入到计算机中,并存储在存储器或是磁盘上的。在这点上,用户程序被简单地 看作是字符数字流的一个集合。当汇编程序执行时,它读取用户程序做分析,然后生成所需要 的机器语言程序。而机器语言程序中包含着将要被计算机执行的用0 和 1 模式说明的指令。按 照原始的字符数字文本形式组成的用户程序叫做源程序(source program),汇编后的机器语言 程序叫做目标程序(object program)。我们将在 2.5.2 节和第 4 章中讨论汇编程序是如何工作 的。首先给出一些汇编语言本身的外部特征。

一台给定计算机的汇编语言可能是大小写敏感的也可能不是,也就是说,它可以区别也 可以不区别大写和小写字母。在本节的例子中,为了提高文本的易读性,我们使用大写字母表 示所有的名称和标号。例如,将Store 指令写成:

ST R2, SUM

助记符ST 表示这条指令所执行操作的二进制模式,或叫做操作(OP)码。汇编程序将这个助 记符翻译成这台计算机能够识别的二进制OP 码。

OP 码助记符后面最少跟随一个空格字符或制表符,再后面的信息给出了具体的操作数。

45~ 48

在上面的Store 指令中,源操作数在寄存器 R2 中。这个信息后面跟随的是目的操作数的具体

ADDI R2, R3, 5

助记符ADDI 中的后缀 I 表示第二个源操作数是用立即寻址方式给出的。

间接寻址通常由放置在圆括号中的代表指向操作数的指针的名字或符号来表示。例如,

如果寄存器R2 包含存储器中一个数的地址,那么可以通过如下指令将这个数加载到寄存器 R3 中:

LD R3, (R2) 2.5.1 汇编指示

R4, #NUM1 Move

在存储器的什么位置存放指令。

在存储器的什么位置存放数据操作数。

为 了 提 供 这 些 信 息, 源 程 序 可 以 写 成 如 图2-13 所示的形式。这个程序以汇编指示 ORIGIN 开始,ORIGIN 告诉汇编程序在存储器的什么位置存放后面的指令。它指明了目标程 序的指令将要被装载到存储器中起始地址为100 的连续单元中。跟在后面的是用适当的助记符 和语法编写的源程序指令。注意到我们使用了语句

BGT R2, R0, LOOP 来表示一条执行下面这个操作的指令:

Branch_if_[R2]>0 LOOP

第二个汇编指示ORIGIN 告诉汇编程序在存储器的什么位置存放后面的数据块。在本 例中,被指明的单元地址是200。这是要用来存放最后总和的单元。通过使用汇编指示符 RESERVE 来为总和保留 4 个字节的空间。在地址 204 中的下一个字,必须包含列表中条目的 数量150。DATAWORD 指示符是用来告诉汇编程序这个要求的。下一个 RESERVE 指示符声 明预留一个600 字节的存储块来保存数据。这个指示符并不能将任何数据加载到这些单元里。

只有使用输入程序,才能把数据装入该存储器中,就像我们将在第3 章中解释的那样。源程序 中最后一个语句是汇编指示END,它告诉汇编程序这里是源程序正文的结束点。

ORIGIN 100 LD R2, N

3 R R

L C

1 M U N

# , 4 R V

O M

LOOP: LD R5, (R4) ADD R3, R3, R5 ADD R4, R4, #4 SUB R2, R2, #1 BGT R2, R0, LOOP ST R3, SUM

ORIGIN 200 SUM: RESERVE 4 N: DATAWORD 150 NUM1: RESERVE 600

END 存储器地

址标号 操作 寻址或数据信息

汇编指示

生成机器指令的语句

下一条指令 汇编指示

图2-13 图 2-12 中程序的汇编语言表示形式

我们先前已经描述了EQU 指示符是如何将一个指定的值(可能是一个地址)与一个特 定的名字关联起来的。在图2-13 中阐明了一种把地址与名字或标号关联起来的不同方法。我 们可以为任何指令和存储单元中的数据指定一个存储器地址标号。汇编程序自动为这个标号 分配该单元的地址。举个例子,对于跟在第二个ORIGIN 指示符之后的数据块,我们用标号 SUM、N 和 NUM1 来标记。因为 ORIGIN 指示符之后的第一个 RESERVE 语句被指定了标号 SUM,所以就为名字 SUM 分配值 200。每当在程序中遇到 SUM,它都被替换成这个值。这种 将SUM 当作一个标号的方式等价于使用以下的汇编指示:

50~ 51

52

SUM EQU 200

类似地,标号N 和 NUM1 被分别分配了值 204 和 208,因为它们表示两个紧跟在地址为 200 的字单元之后的字单元地址。

大多数汇编语言要求源程序中的语句按以下方式编写:

标号: 操作 操作数 注释

这四个字段(field)采用适当的定界符,可能用一个或多个空格或者制表符进行分隔。标号可 以是任意与存储器地址相关的名字,该语句所生成的机器语言指令将被装入这个地址中。标号 也可以与数据项的地址相关联。在图2-13 中有四个标号:LOOP、SUM、N 和 NUM1。

操作字段中包含着一个汇编指示符或所需指令的OP 码助记符。操作数字段包含着用于访 问操作数的寻址信息。注释字段将被汇编程序忽略,它是使程序更容易理解的文档。

我们已经介绍的仅仅是汇编语言最基本的特性。不同计算机在这些语言的细节和复杂程 度上是不相同的。

2.5.2 程序的汇编和执行

用汇编语言编写的源程序在能够被执行之前必须被汇编成机器语言的目标程序。这是由 汇编程序来完成的,它将用在机器指令中使用的二进制码替换所有表示操作的符号以及寻址方 式,并且将所有的名字和标号用它们的实际值替换。

汇编程序为指令和数据块分配地址,起始地址由汇编指示符ORIGIN 给出。它还插入一 些可能是在DATAWORD 命令中给出的常数,并按 RESERVE 命令的要求保留存储空间。

汇编处理的一个关键部分是确定那些将要用来替代名字的值。在某种情况下,名字的值 是由EQU 指示符说明的,这是一种简单的方式。在另一些情况下,名字是由一条给定指令的 标号字段定义的,用这种名字表示的值是由汇编后的目标程序中这条指令所在的位置决定的。

因此,汇编程序必须在生成连续指令的机器码时时刻注意地址的值。例如,图2-13 程序中的 名字LOOP 和 SUM 将分别被分配的值是 112 和 200。

在有些情况下,汇编程序不直接用一个地址的实际值去取代表示这个地址的名字。例如,

在一条转移指令中,用于指明将要转入的那个位置(转移目标)的名字不用实际的地址替换。

转移指令通常是在机器码中用指定转移目标的方法来实现的,转移目标被指定为从程序计数 器中的当前地址到目标指令之间的距离(以字节为单位)。汇编程序计算转移偏移量(branch offset),偏移量可正可负,并将它放进机器指令中。我们将在 2.13 节中展示转移指令是如何实 现的。

汇编程序将目标程序存储在计算机中可用的辅助存储设备中,通常是磁盘。在目标程序 开始执行之前,它必须被装入计算机的主存储器中。为了完成这项工作,另一个叫做装载程序

(loader)的实用程序必须已经在存储器中了。执行这个装载程序就是运行一系列的输入操作,

将机器语言程序从磁盘中传送到存储器中指定的位置上。装载程序必须知道这个程序的长度和 将要存放它的存储器地址。汇编程序通常把这些信息放在目标代码的头部。装载完目标代码 后,装载程序就转移到将要执行的第一条指令处开始执行目标程序,将要执行的第一条指令可 能由一个地址标号如START 来识别。汇编程序把这个地址放到目标代码的头部供装载程序在 执行时使用。

当目标程序开始执行后,它会一直进行到结束,除非在程序中有逻辑性错误。用户必须 能够容易地发现错误,汇编程序只能够监测并报告语法错误。为了帮助用户发现其他的程序设 计错误,系统软件通常提供一个调试(debugger)程序。这个程序使用户能够在一些感兴趣的

53

点上停止目标程序的运行,去检查各个处理器寄存器和存储单元的内容。

在这一小节中,我们介绍了一些关于程序汇编和运行的重要问题。第4 章将会更详细地 讨论这些问题。

2.5.3 数的表示

在处理数值的时候,使用熟悉的十进制记数法通常是很方便的。当然,这些值是用二进 制方式存储在计算机中的。有些情况下,直接指定二进制模式是比较方便的。大多数汇编程序 允许数值在汇编语法定义的约定下有多种表示方式。例如,考虑数字93,它用 8 位二进制数 表示为01011101。如果这个值被当作立即操作数使用,它可以作为一个十进制数给出,就像 如下的指令:

ADDI R2, R3, 93

或者用一个汇编程序指定的前缀符号(比如百分号)识别成二进制数,比如:

或者用一个汇编程序指定的前缀符号(比如百分号)识别成二进制数,比如: