Assembly 等同于其他体系结构上的Z80 DJNZ指令?

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

首先是一点背景知识。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_version_erase_loop ; loop 
当然,您可以使用常规比较和跳转指令执行相同的操作,但通常使用单个指令很方便


这样一来,我的问题是,其他CPU体系结构是否包含类似的控制指令?

IA-32有各种
REP*
指令,它们使用CX作为计数器

存在单个指令集计算机,它们实际上没有被使用。但其中一种单指令集机器是“小于或等于零时进行减法和分支”(
subseq
)机器


我不知道有任何其他真正的机器有这样的指令。我喜欢RISC机器,也不认为有必要使用它。

这是那个时代机器上相当常见的指令,在许多其他地方也有

  • 同样地
  • 极简主义者 ISZ—递增操作数,如果结果为零则跳过

等等

PDP-11(大约1970年)比Z-80早了大约5年,至少有些型号(虽然可能不是早期型号)有减法1和分支指令:

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完全不同的操作码。