



CISC处理器支持多种寻址方式,在内存和寄存器之间进行数据传输。而RISC处理器仅支持少数寻址方式。每种处理器体系结构在定义其寻址方式时,都要分析软件的预期内存访问模式。
本节将用一个简单的6502代码示例来介绍6502的寻址方式,其功能是将4个字节类型的数据相加。为了简单起见,该例忽略了8位和的任何进位。
在立即寻址中,操作数的数值紧跟在内存中的操作码之后。在第一个示例中,假设给定了4个字节的值,要求编写6502程序来对这4个字节的数据求和,在程序代码中将直接使用这几个字节的值。本示例中的字节数据为$01~$04,此处将以相反的顺序($04~$01)将这4个字节相加,这样做的目的是便于在后面使用循环结构。下面的代码使用立即寻址方式将4个字节相加:
需要注意的是,汇编语言的注释以分号开头。当这些指令执行完成后,A寄存器中保存的值是$0A,也就是这4个字节数据的和。
回顾第1章,在6502汇编语言中,字符#表示该值是立即数,而字符$表示该值是十六进制数。立即寻址的操作数是从存放指令操作码之后的内存单元中读取的。因为不需要为要读取的操作数保留内存空间,所以立即寻址比较便捷。但是,只有数据值在编写程序时已知的情况下,才能够使用立即寻址方式。
绝对寻址方式 (absolute addressing mode,又称为直接寻址方式)由指令指明需要读取或写入的数据的内存地址。因为6502使用16位地址,所以访问所有可用内存的地址字段的长度是两个字节。访问任意6502内存位置数据的完整指令由三个字节组成:第一个字节是操作码,后两个字节用于指明读取或写入的地址(这两个地址字节必须是低位字节在前,高位字节在后)。
由于两个字节地址的低位字节存储在低位内存地址中,因此6502是一个 小端 (littleendian)处理器。X86也属于小端处理器。ARM和RISC-V体系结构允许在软件的控制下决定使用大端(big-endian)模式还是小端模式[称为 双端 (bi-endianness)],但是在这些体系结构上运行的大多数操作系统会选择小端模式。
绝对寻址方式的示例中,开始是一段初始化代码,将4个字节存入地址为$200~$203的内存单元。接下来是实现4个字节相加的代码。下面是用绝对寻址方式对4个字节进行求和的例子:
与立即寻址方式不同,绝对寻址方式允许在程序执行期间对4个字节进行求和操作:ADC指令把存储在地址$200~$203中的4个字节加到一起。这种寻址方式的一个限制是要执行求和操作的字节的地址必须在程序编写时就被指定。这个程序不能再对内存的其他字节进行求和。
这个简单示例的缺点是将相似度很高的指令序列堆放在一起。为了避免这种情况,通常需要将重复的代码放入循环结构。接下来的两个例子利用6502的寻址方式使得循环容易实现,不过在第二个示例中才能实现循环。
绝对索引寻址方式
(absolute indexed addressing mode)通过把指令提供的基址与暂存在X寄存器或Y寄存器的值相加得到内存地址
。以下示例用绝对索引寻址方式将地址$0200~$0203中的字节相加。X寄存器提供了相对于字节数组基地址$0200的偏移量:
其中DEX指令使X寄存器递减(X寄存器减1)。尽管这段代码会使得4个字节相加所用的指令数量增加,但是需要注意的是,指令序列DEX、ADC $0200、X重复了三遍。
通过使用条件分支,可以在一个循环中执行相同的加法序列:
BPL(branch on plus)指令指在一定条件下将控制转移到前面带有ADD_LOOP标签的指令处。只有当处理器中的N标志被清除时,BPL指令才执行分支,但如果N标志置位,则BPL指令将继续执行下一条指令。
在上面的示例中,为了累加4个字节的数据去构造一个循环似乎有些不值得。但是,可以通过简单地更改LDX指令的操作数来修改这个版本的代码,即可将100个连续字节进行求和。用相同的方式扩展这个示例,将100个字节相加需要更多的工作,并且指令将消耗更多的内存。
这个示例与绝对寻址方式有相同的限制:在编写程序时,将字节数组的起始位置保存在已经定义好的内存单元中。在接下来的寻址方式中将消除这种限制,并且可以对内存中从任何位置开始的字节数组进行求和。
间接索引寻址方式 (indirect indexed addressing mode)使用存储在内存地址范围$00~$FF中的两个字节作为基地址,并将Y寄存器的内容与该基地址相加,从而生成指令所需的内存地址。在下面的示例中,首先将字节数组的基地址($0200)以小端模式存储在地址$0010和$0011处。该代码在循环体中使用间接索引寻址将字节相加:
由于使用了间接索引寻址,因此执行求和代码之前,任何内存地址都可以存储到地址$10~$11中。需要注意的是,间接索引寻址一定要用Y寄存器暂存地址偏移量,而X寄存器在这种模式下不可用。
6502还有一些其他的寻址方式。 零页寻址方式 (zero-page addressing mode)通过只使用$00~$FF范围内的内存地址,使得指令长度更短(减少了一个字节)且能快速地执行绝对寻址和绝对索引寻址。术语零页指在$00~$FF范围内16位地址的高字节为零。除了更快的执行速度和更少的内存需求,零页寻址方式的行为与前面所述的寻址方式相同。
另一种寻址方式是 索引间接寻址方式 (indexed indirect addressing mode),它与间接索引寻址方式类似。不同之处在于,它使用X寄存器代替Y寄存器,将X寄存器中暂存的偏移量与指令提供的地址相加,来确定指向数据的指针地址。例如,X寄存器值为8,LDA($10,X)指令会将X寄存器的值与$10相加,产生的结果为$18。然后,这个指令从地址$18~$19中读取的16位数据用作内存地址去访存,将读取的数据加载到A寄存器中。
索引间接寻址与字节序列求和的示例无关,这种寻址方式的一个示例应用程序是从连续的指针列表中选择一个值,其中每个指针都指向一个字符串的地址。X寄存器可以引用其中一个字符串作为指针列表起始的偏移量。类似于LDA($10,X)的指令会把所选的字符串地址加载到A寄存器中。
CISC和RISC处理器中的各种寻址方式都是为了支持高效地访问系统内存中的各种数据结构,只不过RISC处理器的寻址方式比CISC少一些。
下一节将讨论6502体系结构中实现的指令类型以及每条指令如何使用相关的寻址方式。