|
65816指令集3
区段移动指令
MVP:正向移动(目标地址>源地址)
MVN:负向移动(目标地址<源地址)
这是65816的新指令。MVN和MVP可以在没有用户干预的情况下移动内存的数据。
这两个指令都是必需的,这样才能确保数据在进行负方向移动时不会覆盖自身。
移动的源地址从X寄存器中取得,目标地址从Y寄存器中取得。移动数据的长度(16位)从累加器中取得,而不需要理会m标志的值。这个长度值应该是实际移动的长度减去1(比如a=$0000,会移动1个字节)。
两个操作数字节指定了来源的64K存储段和目标的64K存储段。操作数字节在汇编程序中的顺序是来源,目标--然而,实际的二进制输出代码会是目标存储段字节,来源存储段字节,最后才是MVN或者MVP的操作码。
当来源地址比目标地址大时,使用MVN进行负方向移动,或者在目标内存段范围小于来源内存段范围时使用MVP。
MVN指令使用X和Y寄存器来指示两个被移动的内存段的底部(开始)地址。通过MVN,数据从X中的来源地址移动到在Y中的目标地址,然后X和Y寄存器递增,累加器递减,直到累加器下溢$FFFF。
当源地址小于目标地址时,使用MVP进行正向移动,或者在目标内存段范围大于来源内存范围时使用MVN。
MVP指令使用X和Y寄存器来指示两个被移动的内存段的顶部地址。数据从X中的来源地址移动到在Y中的目标地址,然后XY寄存器和累加器都递减,直到累加器下溢$FFFF。
如果变址寄存器被设成8位模式(x=1)或处理器被设成6502模拟模式,那么数据移动将会被局限在页面零内,因为高端字节总是零。
可以很容易地在子程序内使用移动指令,然后在运行时动态地修改代码以交换MVN和MVP操作码,这样可以减少代码的长度。
状态寄存器标志不会受移动指令的影响。 寻址方式语法操作码指令长度周期区段移动 MVN src,dest 54 3 * 区段移动 MVP src,dest 44 3 *
NOP:空操作
和在6502下一样,NOP指令不会影响任何标志 寻址方式语法操作码指令长度周期隐式寻址 NOP EA 1 2
ORA:与累加器。
功能和6502下的ORA相同,但是用了新的寻址方式。在16位内存/累加器模式(m=0)下,被操作的数据是16位宽的。低端字节来自有效地址,高端字节来自有效地址的下一个存储单元。 该指令会影响的标志 n-----zc
n:在结果的最高有效位被设置时设置。 z:如果结果是零则设置。 寻址模式语法操作码指令长度周期备注直接寻址 ORA #const 09
2*
2
1 绝对寻址 ORA addr 0D
3
4
1 绝对长程寻址 ORA long 0F
4
5
1 直接页面寻址 ORA dp 05
2
3
1,2 直接页面间接寻址 ORA (dp) 12
2
5
1,2 直接页面间接长程寻址 ORA [dp] 07
2
6
1,2 绝对变址X寻址 ORA addr,X 1D
3
4
1,3 绝对变址X长程寻址 ORA long,X 1F
4
5
1 绝对变址Y寻址 ORA addr,Y 19
3
4
1,3 直接页面变址X寻址 ORA dp,X 15
2
4
1,2 直接页面变址X,间接寻址 ORA (dp,X) 01
2
6
1,2 直接页面间接,变址Y寻址 ORA (dp),Y 11
2
5
1,2,3 直接页面间接长程,变址Y寻址 ORA [dp],Y 17
2
6
1,2 堆栈相对寻址 ORA sr,S 03
2
4
1 堆栈相对间接,变址Y寻址 ORA (sr,S),Y 13
2
7
1* [td]如果m=0(16位内存/累加器),则增加一个字节 | 1 [td]如果m=0(16位内存/累加器),则增加一个周期 | 2 [td]如果直接页面寄存器的低端字节不为零,则增加一个周期 | 3 [td]如果增加变址越过页面边界,则增加一个周期 |
PEA:有效绝对地址压栈
PEA将16位的操作数压入堆栈。堆栈指针减2。该指令不会影响任何标志。不像其他使用汇编程序助记符的指令,PEA是将操作数的值压入堆栈,而不是将位于有效地址的数据压入堆栈。其实它更合适的名字应该是直接数据压栈--不知道为什么它不这么叫。 举例来说:
PEA $1234
会将#$12和#$34依次压栈。 寻址模式语法操作码指令长度周期堆栈(绝对)寻址 PEA addr F4 3 5
PEI:有效间接地址压栈
这个65816个指令将有效地址的地址压入堆栈。这个指令总是向堆栈压入16位的数据而不理会m和x状态位的值。
有效地址的下一个存储单位的地址首先被压入堆栈,然后是有效地址的地址被压栈。 举例来说:假如$5678按标准的低端字节/高端字节的格式被储存在$21/$22,然后执行
PEI ($21)
会从$21/$22取出$5678并且压入堆栈。 寻址模式语法操作码指令长度周期备注堆栈(直接页面间接)寻址 PEI (dp) D4 2 6 11 [td]如果直接页面寄存器的低端字节不是0,则增加1个周期 |
PER:有效程序指针相对间接地址压栈
这个指令把程序指针加上16位的操作数,将获得的16位数据压入堆栈。目标地址必须位于当前的64K内存存储段内。用于计算的程序指针的值是PER之后的下一条指令的地址(两个字节)。
相加结果的高端字节首先被压栈,然后是低端字节。
因为该指令用一个相对的偏移量作为操作数,它会对编写重定位代码有帮助。可以将一个未知的运行时地址压入堆栈,然后将该地址出栈以决定程序运行时起点。
该指令的另一种用途是将6502的pha:pha:rts风格的代码的返回地址压入堆栈。 寻址模式语法操作码指令长度周期堆栈(程序指针相对长程)寻址 PER lable 62 3 6
A,P,X,Y寄存器压栈,出栈指令:
PHA,PHP,PLA,PLP和他们在6502中的前身基本一样。唯一的不同是在16位累加器/内存(m=0)模式下执行PHA或PLA时,压入堆栈的数据将是16位宽的。(PHP/PLP只在8位上操作)
新的压栈出堆栈指令包括PHY,PLY,PHX和PLX。这四条新指令将变址寄存器压栈或者出栈。当状态寄存器被设置到16位变址寄存器模式(x=0),被压栈和出栈的变址寄存器会按16位上操作。 寻址模式标志
助记符操作码指令长度周期备注堆栈(压栈) - - - - - - - - PHA 48 1 3 1 堆栈(压栈) - - - - - - - - PHP 08 1 3 堆栈(压栈) - - - - - - - - PHX DA 1 3 2 堆栈(压栈) - - - - - - - - PHY 5A 1 3 2 堆栈(出栈) n - - - - - z - PLA 68 1 4 1 堆栈(出栈) n v m x d i z c PLP 28 1 4 堆栈(出栈) n - - - - - z - PLX FA 1 4 2 堆栈(出栈) n - - - - - z - PLY 7A 1 4 21 [td]如果是16位内存/累加器(m=0),则增加1个周期 | 2 [td]如果是16位变址寄存器(x=0),则增加1个周期 |
存储段寄存器压栈,出栈指令:
PHB将数据存储段寄存器的8位数据内容压入堆栈。
PHD将直接页面寄存器的16位数据内容压入堆栈。高端字节被先被压栈,然后是低端字节。
PHK将程序存储寄存器的8位数据内容压入堆栈。
PLB将数据存储段寄存器的单字节内容出栈。这是唯一能直接改变数据存储段寄存器的指令。
PLD将直接页面寄存器的双字节内容出栈。低端字节首先出栈,然后是高端字节。 出栈指令会影响的标志:
n:如果出栈的数据的最高有效位被设置,则设置。 z:如果出栈的数据是零则设置。 寻址模式标志
助记符操作码指令长度周期堆栈(压栈) - - - - - - - - PHB 8B 1 3 堆栈(压栈) - - - - - - - - PHD 0B 1 4 堆栈(压栈) - - - - - - - - PHK 4B 1 3 堆栈(出栈) n - - - - - z - PLB AB 1 4 堆栈(出栈) n - - - - - z - PLD 2B 1 5
REP:复位状态位
REP是一个新增的65816指令。当执行时,它会把由单字节直接数据值指定的位复位(清除)。 举例来说明如何清除状态寄存器的位5:
REP #%00100000 ;清除位5
也可以清除多个位: REP #%10110000 ;清除位7,位5和位4
其实任何组合都是可以的。
要设置一个位,可以看SEP指令。 会被影响的标志:nvmxdizc
所有操作数中指定的位都会被清除,其他的位则不受影响。 寻址模式语法操作码指令长度周期直接寻址 REP #const C2 2 3
ROL:对内存数据或累加器进行循环左移
ROL和6502下的ROL指令一样地工作。在16位累加器/内存模式(m=0)下,循环移动的数据是16位宽的,先前的位15变成了新的进位标志。低端字节位于有效地址而高端字节位于有效地址的下一个存储单元。 会受影响的标志:n-----zc
n:在结果的最高有效位被设置时设置。 z:如果结果是零则设置。 c:高位(位7或位15)变成新的进位。 寻址模式语法操作码指令长度周期备注累加器寻址 ROL a
2A 1 2 绝对寻址 ROL addr 2E 3 6 1 直接页面寻址 ROL dp 26 2 5 1,2 绝对变址X寻址 ROL addr,X 3E 3 7 1 直接页面变址X寻址 ROL dp,X 36 2 6 1,21 [td]如果m=0(16位内存/累加器),则增加两个周期 | 2 [td]如果直接页面寄存器的低端字节不为零,则增加一个周期 |
ROR:内存数据或累加器循环右移
该指令和6502下的ROR一样地工作。在16位内存/累加器模式(m=0)下,被循环移动的数据将是16位宽的(加上进位),低端字节位于有效地址而高端字节位于有效地址的下一个存储单元。 会受影响的标志:n-----zc
n:在结果的最高有效位被设置时设置。 z:如果结果是零则设置。 c:低位变成新的进位。 寻址模式语法操作码指令长度周期备注累加器寻址 ROR a
6A 1 2 绝对寻址 ROR addr 6E 3 6 1 直接页面寻址 ROR dp 66 2 5 1,2 绝对变址X寻址 ROR addr,X 7E 3 7 1 直接页面变址X寻址 ROR dp,X 76 2 6 1,21 [td]如果m=0(16位内存/累加器),则增加两个周期 | 2 [td]如果直接页面寄存器的低端字节不为零,则增加一个周期 |
RTI:从中断返回
在6502模拟模式(e=1)下RTI和在旧6502下一样地被处理。在65816的原本模式(e=0)下,RTI还将程序存储寄存器字节从堆栈中弹出。由于有这个特别的字节存在,所以要确保在中断执行时,RTI在和处理器相同的模式(e=?)下执行。
会受影响的标志有:状态寄存器从堆栈弹出,所以所有的标志都受影响。 寻址模式语法操作码指令长度周期备注堆栈寻址(RTI) RTI 40 1 6 11 [td]如果在65816原本模式,则增加1个周期 |
RTL:从子程序长程返回
RTL和RTS差不多,但它还将程序存储寄存器弹出堆栈。这个指令应该和JSR长程指令或者和一个将程序存储段压入堆栈的子程序联合使用。RTL从堆栈弹出24位数据。首先是两个字节的程序指针的低端/高端字节被弹出并且递增,然后是程序存储寄存器被弹出。
RTL不会影响任何标志。 寻址模式语法操作码指令长度周期堆栈寻址(RTL) RTL 6B 1 6
RTS:从子程序返回
和6502下的指令一样。不会影响任何标志。 RTS的一种有趣的用法是将返回地址压入堆栈,然后通过RTS运行它。为了使用这种方式来编码,压入堆栈的地址必须至少比真正的子程序地址小1,因为出栈后,处理器会在继续执行之前自动把程序指针加1。当在原本模式中并且使用16位累加器/内存时,这能很容易地用下面的代码完成:
DEC A ;递减16位的累加器。或用DEA。 PHA ;将16位返回地址压栈。 RTS ;返回来执行指令。 寻址模式语法操作码指令长度周期堆栈寻址(RTS) RTS 60 1 6
SBC:从累加器减去
SBC也和在6502下一样地工作。唯一的不同,又是增加了一些新的寻址方式,以及数据也许要在16位累加器或者16位内存存储单元中工作的事实。
在16位内存/累加器模式下使用的SBC和ADC会全面地大幅度提高65816 的程序性能,一个程序员能轻易地看出加法和减法子程序在16位方式下操作比在8位方式下操作快多少。 该指令会影响的标志 nv----zc
n:在结果的最高有效位被设置时设置。 v:如果有符号的溢出则设置。 z:如果结果是零则设置。 c:如果不需要无符号借位则设置。 寻址模式语法操作码指令长度周期备注直接寻址 SBC #const E9
2*
2
1 绝对寻址 SBC addr ED
3
4
1 绝对长程寻址 SBC long EF
4
5
1 直接页面寻址 SBC dp E5
2
3
1,2 直接页面间接寻址 SBC (dp) F2
2
5
1,2 直接页面间接长程寻址 SBC [dp] E7
2
6
1,2 绝对变址X寻址 SBC addr,X FD
3
4
1,3 绝对变址X长程寻址 SBC long,X FF
4
5
1 绝对变址Y寻址 SBC addr,Y F9
3
4
1,3 直接页面变址X寻址 SBC dp,X F5
2
4
1,2 直接页面变址X,间接寻址 SBC (dp,X) E1
2
6
1,2 直接页面间接,变址Y寻址 SBC (dp),Y F1
2
5
1,2,3 直接页面间接长程,变址Y寻址 SBC [dp],Y F7
2
6
1,2 堆栈相对寻址 SBC sr,S E3
2
4
1 堆栈相对间接,变址Y寻址 SBC (sr,S),Y F3
2
7
1* [td]如果m=0(16位内存/累加器),则增加一个字节 | 1 [td]如果m=0(16位内存/累加器),则增加一个周期 | 2 [td]如果直接页面寄存器的低端字节不为零,则增加一个周期 | 3 [td]如果增加变址越过页面边界,则增加一个周期 |
|
|