跳转到内容

360 汇编/360 指令/BC

来自维基教科书,开放的书籍,为开放的世界

BC - 根据条件跳转 - RX 类型指令 - 操作码 47 / 十进制 71

可用性

[编辑 | 编辑源代码]

BC 指令在所有型号的 360、370 和 z/System 上都可用。

BC 2,LABEL
BH LABEL - 特殊操作码,与 BC 2,LABEL 相同
BC 1,L1
BO L1 - 与 BC 1,L1 相同
BC 15,106(0,10)
B 106(0,10) - B 操作码是无条件跳转,与 BC 15 相同
BC 3,256(7,6)

具体的语法是

BC mask,offset(index register,base register)

其中,如果使用了 USING 伪指令,并且目标地址标签位于某个基址寄存器的值 4096 字节范围内,那么汇编程序将自动确定 offsetindex registerbase register 的值。

RX 指令 (4 字节)
字节 1 字节 2 字节 3 和 4
掩码 目标地址
(8 位)
操作码
47
(4 位)

0..F
(4 位)
索引
寄存器

0..F
(4 位)
基址
寄存器

0..F
(12 位)
偏移量
0..FFF
  • 第一个参数是 mask,条件码将与之比较。
  • 第二个参数是如果掩码与当前设置的条件码匹配则要转移到的位置。偏移量值将添加到基址寄存器和索引寄存器中的值以形成目标地址。大多数指令使用都倾向于使用一个基址寄存器,索引寄存器为零,但如果使用两个非零寄存器,无论哪个寄存器是基址寄存器,哪个是索引寄存器,目标地址都将相同。
  • maskbase_registerindex_register 的值范围为 0 到 15。偏移量值的范围为 0 到 4095。
  • 如果 maskbase_register 为零,则指令为无操作,不会跳转。
  • 如果 mask 为 15,则跳转为无条件跳转(除非 base register 为 0,在这种情况下不会跳转)。
  • 如果指定的 index_register 为 0,则不会使用 index_register 中的值。

在执行更改条件码的指令后,计算机会在 PSW 的“条件码”字段中设置 CC 标志位。然后,如果选择的条件码与该指令中的掩码匹配,则该指令可以跳转。例如,假设我们使用算术加寄存器“AR”。然后,在以下情况下,“条件码”的值将如下所示

条件 符号 PSW 中的条件码
结果为零 Z 0
结果为负 N 1
结果为正 P 2
结果溢出 O 3

然后考虑指令“BNZ”(非零分支)。它的掩码是 7。这意味着什么?如果结果不为零,则该指令会跳转,这意味着如果条件码的值不为零,则该指令会跳转!所以它为 1、2 或 3。考虑下表

Z N P O
0 1 1 1

上面的示例给了我们掩码 (0111) = 7。对于以下每个操作码,您可以构建 ZNPO 表,并找到相应的掩码。

其他操作码

[编辑 | 编辑源代码]

汇编程序在几个可选操作码中提供掩码。这些操作码只需要目标地址。这些操作码是

操作码 掩码 用法 目的 等效于 用法
NOP 0 NOP   LABEL 无操作 BC    0,LABEL 任何需要无操作/填充的地方
BO 1 BO    LABEL 溢出/全 1 分支 BC    1,LABEL 在算术运算或算术比较之后,如果发生算术溢出或结果为全 1
BH 2 BH    LABEL 分支(a 高) BC    2,LABEL 在任何比较之后,如果比较中的第一个值高于第二个值,则跳转(A > B
BP 2 BP    LABEL 正分支 BC    2,LABEL 在算术运算或算术比较之后,如果结果为正,则跳转
BL 4 BL    LABEL 分支(a 低) BC    4,LABEL 在任何比较之后,如果第一个值低于第二个值,则跳转(A < B
BM 4 BM    LABEL 负/混合分支 BC    4,LABEL 在算术运算或算术比较之后,如果结果为负或为 1 和 0,则跳转
BNE 7 BNE   LABEL 不等分支 BC    7,LABEL 在任何比较之后,如果第一个值不等于第二个值,则跳转(A <> BA ~= BA != B
BNZ 7 BNZ   LABEL 非零分支 BC    7,LABEL 在算术运算或算术比较之后,如果结果不为零,则跳转
BE 8 BE    LABEL 分支(a 等于 b) BC    8,LABEL 在任何比较之后,如果第一个值等于第二个值,则跳转(A = BA == B
BZ 8 BZ    LABEL 零分支 BC    8,LABEL 在算术运算或算术比较之后,如果结果为零,则跳转
BNL 11 BNL   LABEL 分支(a 不低) BC    11,LABEL 在任何比较之后,如果第一个值不低于第二个值,则跳转(A >= B
BNM 11 BNM   LABEL 非负分支 BC    11,LABEL 在算术运算或算术比较之后,如果结果为零,则跳转
BNH 13 BNH   LABEL 非高分支 BC    13,LABEL 在任何比较之后,如果第一个值不高于第二个值,则跳转 {A<=B)
BNP 13 BNP   LABEL 非正分支 BC    13,LABEL 在算术运算或算术比较之后,如果结果不为正,则跳转
BNO 14 BNO   LABEL 非全 1 分支 BC    14,LABEL 在算术运算或算术比较之后,如果结果不为全 1,则跳转
B 15 B     LABEL 分支(无条件) BC    15,LABEL 在所有情况下都跳转(除非索引寄存器为 0;在这种情况下,将视为无操作)等效于高级语言中的 GOTO

可选格式

[编辑 | 编辑源代码]

对于左侧显示的示例机器代码,假设地址 LABEL 位于寄存器 10 的偏移量 106 (06A 十六进制) 处,并且地址 X1 假设位于基址寄存器 6 和索引寄存器 7 的总和的偏移量 256 (0100 十六进制) 处。

掩码值被忽略

[编辑 | 编辑源代码]
47F0A06A        B    LABEL   unconditional branch -  equivalent to BC 15,label
47076100        NOP  X1      no-operation - BC 0,X1
47FC0006        BC   15,6(12,0) despite the mask being 15, because the base register is 0,
         *                     this is also a no-op

在对 a 和 b 进行标准比较后使用

[编辑 | 编辑源代码]
4780A06A        BE   LABEL   branch if a equal b - BC 8,label
4720A06A        BH   LABEL   branch if a high - BC 2,label
4740A06A        BL   LABEL   branch if a low - BC 4,label
47776100        BNE  X1      branch if a not equal b - BC 7,X1
47D0A06A        BNH  LABEL   branch if a not high - BC 13,label
4740A06A        BNL  LABEL   branch if a not low - BC 4,label

在算术运算后使用

[编辑 | 编辑源代码]
4710A06A        BO   LABEL   branch on overflow - BC 1,label
47276100        BP   X1      branch on plus - BC 2,X1
4740A06A        BM   LABEL   branch on minus - BC 4,label
4780A06A        BZ   LABEL   branch on zero - BC 8,label
47D0A06A        BNP  LABEL   branch on not plus - BC 13,label
47B0A06A        BNM  LABEL   branch on not minus - BC 11,label
4770A06A        BNZ  LABEL   branch on not zero - BC 7,label

在掩码测试指令后使用

[编辑 | 编辑源代码]
47176100        BO   X1      branch on ones - BC 1,X1
4740A06A        BM   LABEL   branch on mixed - BC 4,label
4780A06A        BZ   LABEL   branch on zeroes - BC 8,label
47E0A06A        BNO  LABEL   branch on not ones - BC 14,label

执行算术运算或比较时,程序状态字中称为条件码的某些位会被置位或清除。在比较两个字段的情况下,左侧值被视为“A”值,右侧值被视为“B”值,比较 A 与 B 的结果测试 A 与 B 的比较方式,可以是低、高、相等或不相等。

在算术运算的情况下,测试结果是正、负、零或是否发生了溢出。

在掩码测试指令的情况下,测试结果是全为 1、全为 0 或 1 和 0 混合。

条件分支指令用于在这样的测试之后,将条件码位与掩码值进行比较。如果掩码中设置的位与条件码中设置的位匹配(或掩码中的所有位都被设置),并且目标地址的基址寄存器不为 0,则目标地址会被放入 PSW 中,作为当前指令的新地址,并执行分支。否则,执行将继续执行条件分支指令后面的下一条指令。

目标地址通过将基址寄存器和索引寄存器的内容加到偏移地址来构造。如果索引寄存器为零,则不使用它的值。

指令目的

[编辑 | 编辑源代码]

条件分支指令是程序中的通用分支指令。它有三种变体:不分支或无操作、根据测试进行条件分支或无条件分支。

无操作

[编辑 | 编辑源代码]

“不分支” - BC 0 - 或“NOP”通常用于创建一个不绑定到现有指令的标签。它可能被宏用来进行对齐,将指令或数据强制到特定边界,但在分支到该指令时不会导致程序异常。它也可以用来提供“空闲”空间,允许在不重新组装程序的情况下对二进制文件进行后期修补。无论掩码值如何,如果分支的基址寄存器也为零,也会发生 NOP。

条件分支

[编辑 | 编辑源代码]

掩码中的位与条件码中的位进行比较。如果掩码中的位与条件码中的位匹配(并且目标地址的基址寄存器不为零),则执行分支。

无条件分支

[编辑 | 编辑源代码]

通过设置掩码中的所有位,例如 BC 15,或使用 B 指令,可以执行到另一个位置的分支(相当于高级语言中的 GOTO)。只要目标地址的基址寄存器不为零,分支就会始终被执行。

典型用法

[编辑 | 编辑源代码]

条件分支和可选格式通常在执行比较或算术运算后使用。在以下代码中,会问一个问题,响应会被与 yes 或 no 进行比较,如果两者都不是,则重新提出问题。'CALL' 宏用于创建一个标准的子程序链接。

CHECKINQ NOP  0(0)                                                            
         CALL INQUIRE,(QUES,1,RESP)                 Call an external module called INQUIRE 
         CLC  RESP(1),QY1                           Compare one byte
         BE   YES                                   "Resp" is the A value in an A:B comparison 
         CLC  RESP(1),QY2
         BE   YES
         CLC  RESP(1),QN1 
         BE   NO                                    Answer was 'N'
         CLC  RESP(1),QN2                           Is it 'n'?
         BNE  CHECKINQ                              Something else, try again
         B    NO                                    Answer was 'n'
QUES     DC   C'Are you ready to start?'            Construct a 'C' language-type
         DC   X'00'                                 string, zero terminated
RESP     DS   C                                     One byte response
QY1      DC   C'Y'                                  Available responses
QY2      DC   C'y'
QN1      DC   C'N'
QN2      DC   C'n'

异常和错误

[编辑 | 编辑源代码]
  • 分支寄存器中包含的目标地址不能为奇数,否则会发生操作异常
  • 分支寄存器中包含的目标地址必须在有效内存范围内,否则会发生操作异常。
  • 目标地址的存储密钥必须与当前进程相同(或该进程的密钥必须为 0),否则会发生内存保护违规异常。


替代分支指令

[编辑 | 编辑源代码]
  • BALR 指令用于分支到寄存器中的地址,并将当前地址保存为返回地址,类似于高级语言中的过程或函数调用。
  • BCR 指令与 BC 指令的使用方式相同,但用于分支到指定第二个参数寄存器中的地址。
  • BCT 指令用于将寄存器减 1,然后在结果不为零的情况下分支到指定的地址。
  • BCTR 指令用于将寄存器减 1,然后在结果不为零的情况下分支到第二个参数中指定的寄存器中的地址。
  • BRC 指令用于分支到相对于当前程序计数器的地址,该地址包含在一个立即(16 位)值中。
  • BRCL 指令用于分支到相对于当前程序计数器的地址,该地址包含在一个立即(32 位)值中。
上一条指令
BASSM
360 汇编指令   下一条指令
BCR
上一条操作码
46
下一条操作码
48
华夏公益教科书