Assembly 等同于其他体系结构上的Z80 DJNZ指令?
首先是一点背景知识。z80 CPU有一个名为的指令,它可以以与for循环类似的方式使用。基本上,DJNZ递减B寄存器,如果不是零,则跳到标签。例如:Assembly 等同于其他体系结构上的Z80 DJNZ指令?,assembly,instruction-set,z80,Assembly,Instruction Set,Z80,首先是一点背景知识。z80 CPU有一个名为的指令,它可以以与for循环类似的方式使用。基本上,DJNZ递减B寄存器,如果不是零,则跳到标签。例如: ld b,96 ; erase all of the line disp_version_erase_loop: call _vputblank ; erase pixels at cursor (uses b reg) djnz disp
ld b,96 ; erase all of the line
disp_version_erase_loop:
call _vputblank ; erase pixels at cursor (uses b reg)
djnz disp_version_erase_loop ; loop
当然,您可以使用常规比较和跳转指令执行相同的操作,但通常使用单个指令很方便
这样一来,我的问题是,其他CPU体系结构是否包含类似的控制指令?IA-32有各种
REP*
指令,它们使用CX作为计数器存在单个指令集计算机,它们实际上没有被使用。但其中一种单指令集机器是“小于或等于零时进行减法和分支”(subseq
)机器
我不知道有任何其他真正的机器有这样的指令。我喜欢RISC机器,也不认为有必要使用它。这是那个时代机器上相当常见的指令,在许多其他地方也有
- 李>
- 同样地李>
- 极简主义者 ISZ—递增操作数,如果结果为零则跳过
sob R, offset
PowerPC有一条带特殊倒计时寄存器的
bdnz
指令ctr
。递减ctr
和条件分支位于常规条件测试之上,因此您可以添加一个条件,例如bdnzt eq,如果设置了小于位且递减后ctr
为正值,则标签将进行分支
讽刺的是,ctr
也用于间接函数调用地址。因此,bdnz
在具有间接调用的循环中变得相当无用,因为保存和恢复寄存器的成本超过了ctr
寄存器的特殊优势。指令存在一种编码,“减量ctr
并在不为零时分支到其新值”,但这是特别禁止和限制的。(无论如何,它不会检查空指针。)实际上在IA-32中,DJNZ的直接等价物是LOOPcc(LOOPZ)。请记住,Z80和8086具有相同的前身。
所以所有x86 CPU直接继承DJNZ指令 Z80是一款CISC处理器。DJNZ是复杂指令的经典示例。现代的时尚是RISC指令集,它更喜欢更小、更简单、更快的指令,但可以更快地处理它们——特别是具有高级流水线功能的指令集。例如,我认为在ARM系列上不会出现类似的情况。在x86上,有一条循环指令执行完全相同的操作(ECX中有计数器)。还有一条JECXZ指令(如果ECX为零,则跳转),该指令将与循环一起使用-您将其放在循环之前,以便在开始时计数为零时可以跳过整个循环
像这样:
;number of iterations in ECX
JECXZ end
start:
;loop body
LOOP start
end:
但请注意,这些指令在当代CPU上效率极低。最好使用常规的CMP/SUB和Jcc指令。另一方面,Intel Core2 CPU实际上能够将比较+跳转指令对视为一条指令,他们称之为“宏运算融合”。一些PIC微控制器(如PIC18)具有DECFSZ(减量文件,如果为零则跳过)指令。我经常在DECFSZ后面加上branch。这很有用,因为循环计数器的测试不使用任何标志。如果标志用于循环中的某个对象,则无需担心/反正只有一组标志/寄存器依赖关系管理不是很聪明(例如,电源芯片只能对条件寄存器进行1次重命名)。减量只是普通情况下的一个方便的奖励。(例如,ARM只有比较和分支(如果是零位/非零位)。(作为替代示例,MIPS没有标志寄存器。这是解决此类问题的另一种方法。)CBZ/CBNZ?这是它的一半。我的手臂有点生锈了。。。这可能不是在所有模式下都可用?Intel 8080没有DJNZ指令,它特定于Z80。DJNZ的操作码是8080上的NOP。x86上的循环也具有与DJNZ完全不同的操作码。