360 汇编/360 指令/USING
USING 伪指令 用于告知汇编器各种寄存器的内容,这些寄存器将用于基址-偏移寻址。它不生成任何可执行指令,而是向汇编器提供信息。
USING 伪指令的格式为
- USING 地址,寄存器1[,寄存器2[,...]]
寄存器1 可以是通用寄存器 1 到 15 中的任何一个。它告诉汇编器,该寄存器已加载了作为第一个参数指定的地址。因为许多指令(包括分支指令)将寄存器 0 视为无操作或包含实际值 0,所以不应将寄存器 0 用于此目的。第二个(或后续)寄存器(由参数 寄存器2 指示)可选地提供第二个基址寄存器,并假定它包含第一个参数的地址加上 4096。如果指定了每个后续寄存器,则汇编器假定它包含前一个寄存器中指定的地址以上 4096 个字节的地址。
示例
PROG START 0 BALR 12,0 USING *,12,11 LA 11,4095(12) LA 11,1(11)
在上面的示例中,USING 伪指令告诉汇编器,寄存器 12 被设置为该模块前 4096 个字节的基址寄存器,寄存器 11 被设置为后 4096 个字节的基址寄存器。在通过 BALR 指令将寄存器 12 加载了当前地址后,寄存器 11 将加载程序中 4096 字节之后的地址。请注意,这使用了旧的 LA 指令,该指令不能将超过 4095 的值添加到寄存器中包含的值,因此必须使用两个 LA 指令。虽然这种指令组合可以在所有型号的 IBM 硬件以及竞争对手的设备上运行,但 IBM 硬件的后续版本(如 z/Series)为此目的提供了更高效的指令。
如果多个寄存器都访问同一个特定位置,汇编器可能会感到困惑并发出 MNOTE 级别 4(警告),因为它不确定使用哪个寄存器,在这种情况下,它将使用指向目标地址的编号最高的寄存器。但是,如果两个或多个寄存器的 USING 地址重叠,则汇编器将选择产生最低偏移地址的寄存器。以下示例将演示这一点。此示例来自汇编列表。
000000 1 ************ 000000 2 * Determine which register the assembler uses 000000 3 * Author - Paul Robinson 000000 4 * Date - 11/28/20 000000 5 ***************** 000000 6 TITLE 'Using test' 000000 7 PRINT NOGEN 000000 8 * 000000 9 MAIN CSECT 000000 10 USING MAIN,8 000000 90ECD00C 11 STM 14,12,12(13) 000004 188F 12 LR 8,15 Reg 8 now contiains start address 000006 45F0806C 00006C 13 BAL 15,START 00000C 0000000000000000 14 DC 18F'0' 000054 D4C1C9D540404040 15 DC CL8'MAIN' Create a marker visible during coredumps 00005C F1F161F2F861F2F0 16 DC CL8'11/28/20' Date compiled 000064 F0F14BF0F3404040 17 DC CL8'01.03' Version number of program 00006C 50FD0008 18 START ST 15,8(13) Link savearea to preious savearea 000070 50DF0004 19 ST 13,4(15) 000074 18DF 20 LR 13,15 R13 now points to new savearea 000076 21 USING MAIN+8,13 000076 22 WTO 'Program Started' 000090 28 * 000090 4150D4C0 0004C8 29 LA 5,ITEM 000094 30 * 000094 4120D0D8 0000E0 31 LA 2,BLANKS 000098 4130D4C0 0004C8 32 LA 3,ITEM 00009C 4140D0D4 0000DC 33 LA 4,X 0000A0 34 * 0000A0 35 USING X,4 0000A0 36 USING ITEM,3 0000A0 37 USING BLANKS,2 0000A0 38 * 0000A0 41202000 0000E0 39 LA 2,BLANKS 0000A4 41303000 0004C8 40 LA 3,ITEM 0000A8 41404000 0000DC 41 LA 4,X 0000AC 42 * 0000AC 41503000 0004C8 43 LA 5,ITEM 0000B0 44 * 0000B0 45 WTO 'Program ended.' 0000C8 58D0D004 51 L 13,4(,13) Restore old savearea 0000CC 41F00000 52 LA 15,0 0000D0 58E0D00C 53 L 14,12(,13) 0000D4 982CD01C 54 LM 2,12,28(13) 0000D8 07FE 55 BR 14 And leave 0000DA 56 * 0000DC 00000000 57 X DC A(MAIN) 0000E0 4040404040404040 58 BLANKS DC 1000C' ' 0004C8 00000000 59 ITEM DC A(0) 0004CC 60 END
以下是程序的汇编方式。
- 在第 13 行,分支跳转到程序中的十六进制地址 8C(标签 START),在指令中,它被汇编为 45F0806C,其中 45 是 BAL 指令的十六进制操作码,F 表示寄存器 15,第一个 0 表示未使用索引寄存器,806C 是十六进制地址 08C 加上寄存器 8 中地址的基址-偏移地址,由于第 10 行的 USING 伪指令,因此使用了寄存器 8。
- 在第 29 行,指令被汇编为 4150D4C0,其中 41 是 LA 指令,5 表示寄存器 5 是要加载的目标寄存器,第一个 0 再次表示未使用索引寄存器,并且 {{mono|D4C0|| 用于指示该地址是十六进制地址 4C0 字节加上寄存器 13 中的地址。这是正确的,因为 ITEM 位于程序中的十六进制地址 4dc8。汇编器使用寄存器 13,因为第 21 行的 USING 语句将偏移量放在寄存器 13 中,与寄存器 8 相比,它离 ITEM 只有 8 个字节。
- 类似地,对于第 31-33 行的指令,寄存器 13 中的地址“更接近”(偏移量小于)寄存器 8,因此使用寄存器 13。
- 第 35-37 行的指令告诉汇编器,寄存器 2-4 指向这些位置。
- 在第 39-41 行,由于汇编器已被告知这些寄存器中的每一个都指向它们被告知要加载地址的项,因此在每种情况下,该寄存器与目标地址的偏移量为 0,因此使用该寄存器(偏移量为 0)。
- 在第 43 行,汇编器被告知寄存器 3 与 ITEM 的地址相同,因此汇编器使用寄存器 3 且偏移量为 0。将其与第 29 行的相同指令进行比较,在第 29 行中,寄存器 13 中的地址产生最小的偏移量,因此它被使用而不是寄存器 8。
这是一个内联子程序的示例,该子程序为子程序设置一个临时基址寄存器。出于本示例的目的,假设 R14 等于 14,R15 等于 15 等,以提供交叉引用 - 请参阅 EQU 汇编器伪指令)
* some typical assembler instructions showing comments to the right L R15,=A(MOVE) Load sub-routine address into R15 BALR R14,R15 Go to the sub-routine ===> * ....return here with return code in R15 * ***************************************** * Move the input to output * ***************************************** MOVE EQU * Start of a sub-routine called "Move" USING *,R15 Tell the assembler reg. 15 points to * this address MVC OUTPUT,INPUT Move the input to the output area SR R15,R15 Clear register contents (set Return code = 0) BR R14 return to caller DROP R15 Tell assembler we are no longer using * register 15 and resume using previous register * TABLE DC C'ABCDEFGHIJKLMNOPQRSTUVWXYZ' Table of letters of the alphabet INPUT DS Cl80 Input area OUTPUT DS Cl80 Output area
如上例所示,USING 伪指令告诉汇编器特定寄存器包含指定的地址,而 DROP 伪指令告诉汇编器该寄存器不能再使用,直到在另一个 USING 伪指令中指定它。
按照惯例
- 操作系统通常在 SVC 中使用寄存器 0 和 1,并期望使用一个或两个寄存器提供值或值列表的地址;它们也经常用于(有时与寄存器 15 一起)从 SVC 返回结果值。因此,寄存器 1 不应在可执行代码段中用作基址寄存器,但可以接受引用 DSECT 将标签映射到寄存器 1 的偏移量。
- 某些操作系统和某些指令可能会提供或使用寄存器 2 和/或寄存器 15,因此如果在发出 SVC 或发出 SVC 的宏的汇编语言模块中使用寄存器 2 或 15 作为基址寄存器,则应注意。
- 390/zSystem 硬件上的 Linux 操作系统使用寄存器 1 到 6 用于参数,因此在 S/390 Linux 上进行 SVC 后,不应认为这些寄存器保持不变或可用。
- 寄存器 13 通常用作指向 18 字节寄存器保存区域的指针(对于在 24 或 32 位模式下运行的程序),因此它应该只用于此目的。如果程序没有调用任何子程序并在入口处保存寄存器 13 的值,并在退出时恢复它,则寄存器 13 可以用于任何目的。但是,如果寄存器 13 用于其他目的(其中它不指向保存区域),则应在程序中记录这一点,以便将来维护程序的任何人不会对此做法感到困惑。注意,寄存器 13 可以用于其他目的,例如指向可重写区域(例如,对于动态获取内存的重入程序)或任何其他目的,只要它指向的前 18 个字可用作寄存器保存区域。
- 寄存器 14 通常用作程序返回到调用方(或如果程序不是子程序,则返回到操作系统)的返回地址。如果程序在入口处保存寄存器 14,并在退出时恢复它,则寄存器 14 可以用于任何目的。
- 寄存器 15 通常作为程序的入口点提供,因此可以作为 USING 寄存器;只有当程序本身必须调用子程序时,它才必须将另一个寄存器设置为其基址寄存器。但是,某些操作系统也使用寄存器 15 以及寄存器 0 和 1 返回值,因此如果例程发出 SVC 或发出 SVC 的宏,最好不要将寄存器 15 用作基址寄存器。
地址可以是 *(表示当前程序计数器),也可以是当前模块中的标签,或者标签加上一个值。这允许汇编器知道对当前模块中的地址的引用使用哪个基址寄存器。它也可以在引用 DSECT 时使用,以将 DSECT 中使用的标签分配给基址/偏移地址。
主程序(即不是由调用方加载基址寄存器的子程序)将使用 BALR 或 BASR 指令加载基址寄存器的内容,然后发出 USING 伪指令以告知汇编器该特定寄存器可用作基址寄存器。
360 汇编器 伪指令 | |
地址相关 | ADATA • CNOP • DROP • EQU • LOCTR • LTORG • ORG • USING |
---|---|
代码相关 | ALIAS • AMODE • CATTR • COM • CSECT • CXD • DSECT • DXD • END • ENTRY • EXTRN • OPSYN • RMODE • RSECT • START • WXTRN • XATTR |
数据相关 | CCW • CCW0 • CCW1 • DC • DS |
条件汇编和宏相关 | ACTR • AGO • AIF • AINSERT • ANOP • AREAD • COPY • GBL(GBLA / GBLB / GBLC)• LCL(LCLA / LCLB / LCLC)• MACRO • MEND • MEXIT • MNOTE • SET(SETA / SETB / SETC) |
列表、输出和源代码相关 | 注释 • *PROCESS • ACONTROL • EJECT • END • EXITCTL • ICTL • ISEQ • POP • PRINT • PUNCH • PUSH • REPRO • SPACE • TITLE |
System/360 汇编语言 | |
System/360 系列 | 简介 · 基本常见问题 · System/360 系列 · System/360 架构 |
---|---|
System/360 指令集 | System/360 指令 · 分支指令 · 数据传输指令 · 控制流指令 · 算术指令 · 逻辑指令 · 移位和旋转指令 · 特权指令 · 其他指令 |
语法和汇编器 | System/360 汇编器 · 伪指令 |
指令扩展 | 浮点数 · 高级语言 |