转载

为 z/OS XL C/C++ 编译器使用内联汇编

自 z/OS V1R9 XL C 开始,METAL C 提供了 C 语言扩展来允许直接将高级汇编器 (HLASM) 指令嵌入到 C 程序中。从 z/OS XL C/C++ V2.1.1 开始,您可以将 HLASM 指令嵌入到 C/C++ 程序中。METAL C(在本文中称为 METAL)允许用户直接通过系统提供的汇编宏来利用 MVS™ 系统服务。最新的内联汇编支持(在本文中称为 ASM)允许直接将硬件指令嵌入到标准的 C 和 C++ 程序中,提供全语言环境和运行时库支持。本文将重点介绍 ASM 和 METAL 的特征,以及它们之间的区别。还会介绍如何结合使用 ASMLIB 选项、数据定义名称 (DDname) 与 ASM,搜索源代码中包含的汇编器宏。

ASM 特征

  • ASM 同时支持 C 和 C++ 编译器。
  • 用户更容易使用 ASM 生成对象代码。
  • ASM 支持所有编译器支持的链接,包括 XPLINK 和 NOXPLINK。
  • ASM 支持所有优化级别,包括 OPT(2)、OPT(3)、IPA 和 HOT。
  • ASM 支持所有地址模式,包括 ILP32 和 LP64。
  • 如果用户请求,编译器可以生成调试端文件。
  • ASM 中提供了全语言环境运行时。

回页首

METAL 特征

  • METAL 仅支持 C。
  • METAL 用于系统编程开发。
  • METAL 使用了 MVS 链接约定。
  • METAL 支持所有优化级别,包括 OPT(2)、OPT(3)、IPA 和 HOT。
  • METAL 支持所有地址模式,包括 ILP32 和 LP64。
  • 与语言环境 (LE) 完全独立。
  • METAL 支持用户指定的函数 prolog 和 epilog。

回页首

ASM 与 METAL 的比较

ASM 与 METAL 支持的主要区别如下所示:

表 1. ASM 与 METAL 比较

特征 ASM METAL
支持编译器 C 和 C++ C
控制编译器选项 MVS:ASMUSS:-qasm MVS:METALUSS:-qmetal -S
可用版本 z/OS V2R1M1 z/OS V1R9
硬件架构 所有架构级别 最低 ARCH(5)
HLASM 编译器需求 V2R1 HLASM 和 APAR P121235

V2R2 HLASM
V1R9 HLASM
来自 C/C++ 编译器的输出 对象文件 HLASM 源代码
用户需要调用 HLASM 来编译源代码
链接支持 C 和 C++ 支持的所有链接 仅支持 MVS OS 链接
运行时库支持 z/OS C/C++ 运行时库 z/OS METAL C 运行时库
语言环境支持 否METAL C 生成与 LE 独立的代码
使用自定义的 prolog/epilog 支持
可修改编译器生成的汇编代码
AR 模式支持
AMODE 开关支持

处理区别

以下示例使用了一个简单程序 (example.c) 来演示如何使用 ASM,并使用替代性的 METAL 选项来创建应用程序。执行该应用程序的返回代码为 55。

example.c

int main (void) {    int a=10, b=45 ;    __asm (" AR %0,%1 " :"+r"(a) :"r"(b));    return a; }

示例 1. 在 z/OS UNIX System 服务下使用 ASM 构建应用程序

  1. 编译: xlc –c –qasm example.c
  2. 链接: xlc example.o
  3. 运行: a.out

备注:可将第 1 和第 2 步组合到一步中:

  1. 编译和链接: xlc –qasm example.c
  2. 运行: a.out

示例 2. 在 z/OS UNIX System 服务下使用 METAL 构建应用程序

  1. 编译: xlc -qmetal -S example.c
  2. 汇编: as example.s
  3. 链接: ld –e main example.o
  4. 运行: a.out

示例 3. 通过 z/OS 批处理功能,使用 ASM 构建应用程序

使用 ASM 选项编译应用程序时,可以为每一步使用标准编目过程,或者使用组合编目过程来构建应用程序。

  • 使用 EDCC 进行编译,并使用 CEEWL 链接程序(参见清单 1)。
  • 使用 EDCCB 编译和链接程序(参见清单 2)。
  • 使用 EDCCBG 编译、绑定和运行程序(参见清单 3)。

清单 1. 使用编目过程 EDCC 和 CEEWL 来构建 ASM 应用程序的 JCL

//jobcard information…  //PROC JCLLIB ORDER=(CBC.SCCNPRC, CEE.SCEEPROC) //*------------------------------------------------------------------- //* Compile step //*------------------------------------------------------------------- //COMP   EXEC EDCC, //   OUTFILE='HLQ.OBJECT(EXAMPLE),DISP=SHR', //   CPARM='ASM' //STEPLIB  DD DSN=CBC.SCCNCMP,DISP=SHR //   DD DSN=CEE.SCEERUN,DISP=SHR //   DD DSN=CEE.SCEERUN2,DISP=SHR //   DD DSN=ASM.SASMMOD1,DISP=SHR //COMPILE.SYSIN DD DATA,DLM='/>' int main(void) {  int a=10, b=45 ;  __asm(" AR %0,%1 " :"+r"(a) :"r"(b));  return a; } /> //*------------------------------------------------------------------- //* Link step //*------------------------------------------------------------------- //LINK   EXEC CEEWL, //   PARM= AMODE=31,CASE=MIXED //SYSLMOD  DD DSN=HLQ.LOAD(EXAMPLE),DISP=SHR //OBJECT DD DSN=HLQ.OBJECT,DISP=SHR //SYSLIN DD *   INCLUDE OBJECT(EXAMPLE) /* //SYSPRINT DD SYSOUT=* //*------------------------------------------------------------------- //* Run step //*------------------------------------------------------------------- //GO   EXEC PGM=EXAMPLE //STEPLIB  DD DSN=HLQ.LOAD,DISP=SHR 

清单 2. 使用编目过程 EDCCB 来构建 ASM 应用程序的 JCL

//jobcard information…  //PROC JCLLIB ORDER=(CBC.SCCNPRC) //*------------------------------------------------------------------- //* Compile and bind step //*------------------------------------------------------------------- //COMP   EXEC EDCCB, //   OUTFILE='HLQ.LOAD(EXAMPLE),DISP=SHR', //   CPARM='ASM' //STEPLIB  DD DSN=CBC.SCCNCMP,DISP=SHR //   DD DSN=CEE.SCEERUN,DISP=SHR //   DD DSN=CEE.SCEERUN2,DISP=SHR //   DD DSN=ASM.SASMMOD1,DISP=SHR //COMPILE.SYSIN DD DATA,DLM='/>' int main(void) {  int a=10, b=45 ;  __asm(" AR %0,%1 " :"+r"(a) :"r"(b));  return a; } /> //*------------------------------------------------------------------- //* Run step //*------------------------------------------------------------------- //GO   EXEC PGM=EXAMPLE //STEPLIB  DD DSN=HLQ.LOAD,DISP=SHR 

清单 3. 使用编目过程 EDCCBG 来构建和运行 ASM 应用程序的 JCL

//jobcard information…  //PROC JCLLIB ORDER=(CBC.SCCNPRC) //*------------------------------------------------------------------- //* Compile, bind and run //*------------------------------------------------------------------- //CBG     EXEC EDCCBG, //         CPARM='ASM' //STEPLIB  DD DSN=CBC.SCCNCMP,DISP=SHR //         DD DSN=CEE.SCEERUN,DISP=SHR //         DD DSN=CEE.SCEERUN2,DISP=SHR //         DD DSN=ASM.SASMMOD1,DISP=SHR //COMPILE.SYSIN DD DATA,DLM='/>' int main(void) {    int a=10, b=45 ;    __asm(" AR %0,%1 " :"+r"(a) :"r"(b));    return a; } />

示例 4. 通过 z/OS 批处理功能,使用 METAL 构建应用程序

使用 METAL 选项编译应用程序时,不能使用组合的标准编目过程来编译和绑定程序。这是因为编译器的输出是 HLASM 源代码,在执行链接步骤之前需要通过 HLASM 进行汇编。

清单 4. 使用编目过程 EDCC 和 ASMAC 来编译和汇编 METAL 应用程序的 JCL

//jobcard information... //PROC JCLLIB ORDER=(CBC.SCCNPRC) //*------------------------------------------------------- //* Compile step //*------------------------------------------------------- //COMP   EXEC EDCC, //   OUTFILE='HLQ.ASMSRC(EXAMPLE),DISP=SHR', //   CPARM='METAL' //COMPILE.SYSIN DD DATA,DLM='/>' int main(void) {  int a=10, b=45 ;  __asm (" AR %0,%1 " :"+r"(a) :"r"(b));  return a; } /> //*------------------------------------------------------- //* Assembly step //*------------------------------------------------------- //ASMC   EXEC ASMAC //SYSIN  DD DSN=HLQ.ASMSRC(EXAMPLE),DISP=SHR //SYSLIN DD DSN=HLQ.OBJECT(EXAMPLE),DISP=SHR //*------------------------------------------------------- //* Link step //*------------------------------------------------------- //LINK   EXEC PGM=IEWL, //   PARM= AMODE=31,CASE=MIXED //SYSLMOD  DD DSN=HLQ.LOAD(EXAMPLE),DISP=SHR //OBJECT DD DSN=HLQ.OBJECT,DISP=SHR //SYSLIN DD DATA,DLM='/>'   INCLUDE OBJECT(EXAMPLE)   ENTRY main /> //SYSPRINT DD SYSOUT=* //*------------------------------------------------------- //* Run step //*------------------------------------------------------- //GO   EXEC PGM=EXAMPLE //STEPLIB  DD DSN=HLQ.LOAD,DISP=SHR 

其他区别

在编译过程中,可以将一些编译器选项与 ASM 或 METAL 结合使用,增强内联汇编支持。表 2 显示了哪些选项可与 ASM 或 METAL 结合使用。

表 2. 可编译的编译器选项

编译器选项 ASM METAL
ARMODE
ASMDATASIZE
ASMLIB
DSAUSER
EPILOG
GENASM
KEYWORD(asm) 否 – 在 V2R1M1 以前是 – V2R1M1 和更高版本
PROLOG
RESERVED_REG
SYSSTATE

ASM 和 METAL 在关键字、预定义的宏和编译指示 (pragma) 支持上还有其他区别。表 3 重点介绍了这些区别。

表 3. 其他技术区别

ASM METAL
关键词 asm, __asm, __asm__ __asm, __asm__ 1
编译器预定义宏 __IBM_ASM_SUPPORT = 1 __IBM_METAL__ = 1__IBM_FAR_IS SUPPORTED__ = 1
#pragma insert_asm 不支持 是否支持
_Pragma("insert_asm") 不支持 是否支持

1 如果想要在嵌入的汇编语句中使用关键字或标志 ASM,可以执行以下操作来接受标志 ASM:

  • 在源代码中,添加以下语句之一:
    • #define asm __asm
    • #define asm __asm__
  • 指定编译器选项 KEYWORD(asm)

回页首

ASMLIB

可通过 3 种方式告诉编译器,在何处找到包含在 ASM 语句中的宏:

  1. ASMLIB 编译器选项
  2. ASMLIB DDname 语句
  3. 在上述二者中,编译器选项优先

编译器选项

此选项为编译器提供宏库的搜索路径。指定的宏库可以是 Partitioned Data Set (PDS)、Partitioned Data Set Extended (PDSE) 或 UNIX System Service (USS) 目录,或者所有 3 种库的组合。

  • NOASMLIB
    • NOASMLIB 是默认选项;它表示不给 ASMLIB DD 分配任何库
    • 不接受子选项
    • 清除任何以前的 ASMLIB 选项中指定的所有宏库
    • 如果 ASMLIB DDname 已分配,不要解除分配它
  • ASMLIB( lib1,lib2,.. )
    • 子选项只接受完全限定的 PDS 名称、PDSE 名称和 USS 目录。
    • 所有数据集名称必须以 // 开头。例如 ASMLIB( //'SYS1.MACLIB')
  • 多种 ASMLIB 规范会导致按指定库的顺序将它们串联起来。

示例

表 4 展示了如何通过 ASMLIB 编译器选项搜索用户定义的宏和系统宏。

表 4. ASMLIB 选项用法示例

变体 选项规范
PDS/PDSE MVS:CPARM=' ASMLIB(//'SYS1.MACLIB')'
USS:-qasmlib="//'SYS1.MACLIB'"
结果:搜索数据集 ‘SYS1.MACLIB’
USS 目录 MVS:CPARM='ASMLIB(/hlq/mymacrolib)'
USS:-qasmlib=/hlq/mymacrolib
结果:搜索目录 /hlq/mymacrolib
多个选项和混合类型 MVS:CPARM='ASMLIB(/hlq/mymacrolib) , ASMLIB(//'HLQ.MYMACLIB')'
USS:-qasmlib=/hlq/mymacrolib –qasmlib= "//'HLQ.MYMACLIB'"
结果:搜索 /hlq/mymacrolib 和 ‘HLQ.MYMACLIB’
多个子选项和混合类型 MVS:CPARM='ASMLIB(//'HLQ.MYMACLIB', /hlq/mymacrolib, //'SYS1.MACLIB')'
USS:-qasmlib=“//’HLQ.MYMACLIB’”:/hlq/mymacrolib:’’//’SYS1.MACLIB’”
结果:搜索 ‘HLQ.MYMACLIB’、/hlq/mymacrolib 和 ‘SYS1.MACLIB’
NOASMLIB MVS:CPARM='ASMLIB(/hlq/mymacrolib), NOASMLIB, ASMLIB(//'HLQ.MYMACLIB')'
USS:-qasmlib=/hlq/mymacrolib -qnoasmlib -qasmlib=“//’HLQ.MYMACLIB’”
结果:仅搜索 ‘HLQ.MYMACLIB’

DDname

  • 允许多条包含数据集和 USS 目录的 DD 语句(参见清单 5)。
  • 同时在 JCL 中指定了 ASMLIB 编译器选项和 ASMLIB DD 语句时,这些库会串联成一个搜索列表。编译器选项优先于 DDname(参见清单 6)。

清单 5. ASMLIB DDname 示例

//ASMLIB   DD DSN=SYS1.MACLIB,DISP=SHR  //         DD DSN=HLQ.MYMACLIB,DISP=SHR  //         DD PATH='/hlq/mymacrolib',  //            PATHOPTS=(ORDONLY,ONONBLOCK),  //            PATHMODE=(SIRUSR,SIXUSR),  //            FILEDATA=TEXT

结果:编译器使用以下搜索顺序:

  1. 数据集 SYS1.MACLIB
  2. 数据集 HLQ.MYMACLIB
  3. 目录 /hlq/mymacrolib

清单 6. ASMLIB 编译器选项和 DDname 的示例

//COMP     EXEC EDCC,  //         CPARM='ASM OPTFILE(DD:XOPTS)'  //XOPTS    DD DATA,DLM='/>'     ASMLIB(//'HLQ.MYMLIB1',/hlq/mymacrolib1)     NOASMLIB     ASMLIB(//'HLQ.MYMLIB2',/hlq/mymacrolib2)  />  //ASMLIB DD DSN=SYS1.MACLIB,DISP=SHR  //       DD DSN=HLQ.MYMACLIB,DISP=SHR  //       DD PATH='/hlq/mymacrolib',  //          PATHOPTS=(ORDONLY,ONONBLOCK),  //          PATHMODE=(SIRUSR,SIXUSR),  //          FILEDATA=TEXT

结果:编译器使用以下搜索顺序:

  1. 数据集 HLQ.MYMLIB2
  2. 目录 /hlq/mymacrolib2
  3. 数据集 SYS1.MACLIB
  4. 数据集 HLQ.MYMACLIB
  5. 目录 /hlq/mymacrolib

备注:HLQ.MYMLIB1 和 /hlq/mymacrolib1 被 NOASMLIB 清除。

回页首

结束语

z/OS XLC/C++ 编译器提供的不同的内联汇编支持是为不同用途而设计的。METAL C 用于系统编程开发。ASM 允许用户在标准语言环境中利用汇编宏程序库(assembler macro libraries)和硬件指令。

致谢

感谢 Rajan Bhakta、Visda Vokhshoori 和 Milos Lalovic 为本文提供的帮助和建议。

正文到此结束
Loading...