当我在未使用链接堆栈的程序中发出 PR(程序返回)指令时,程序立即结束。我想利用这种行为,但我想知道除了退出程序之外,我是否会导致任何意外结果?我已经阅读了操作手册中的 PR 描述,但没有看到任何回答我的问题的内容。
如果 PR 指令不适合立即终止程序,我应该使用另一种方法吗?
通常有条目逻辑来保存调用者寄存器。例外情况包括旨在为调用者设置寄存器值的代码。
如果你想返回给你的调用者,BR
返回到BASR
. 简单地退出整个过程并不是一个好主意,因为你不知道你是如何被调用的。也许程序 A 调用了你。也许 A 调用了 B 调用了 C 调用了你,并且 A、B 和 C 都需要在退出之前进行清理工作。我被教导要总是回到你的来电者身边。
虽然今天您知道自己是如何被调用的,但您不知道相关代码正在执行的有用任务是否会在未来被其他程序重用,也许是以前所未有的方式重用。
首先,不存在“不使用链接堆栈的程序”之类的东西,否则您的 PR 指令会导致异常(异常结束)。
此外,来自 IBM 运营原则:
如果当前入口的后向堆栈入口有效性位第63位为零,则识别堆栈空异常,并且操作无效;
这表明不仅存在链接堆栈,而且其上至少有一个帧,否则您的 PR 指令将因堆栈为空条件而失败。
在不使用标准链接的情况下终止程序并返回到您传递的 R14 地址的“标准”方法是发出 SVC 3 指令(SVC 3 是“EXIT”...终止当前 RB)。事实上,如果你仔细观察,你会发现你在进入作业步骤程序时传递的 R14 返回地址只是指向 CVTEXIT,一个 SVC 3 指令,所以这正是你在做在程序结束时执行 BR 14(或其他) - 没有理由您不能自己发布 SVC 3。
将这些拼凑在一起,听起来就像当 z/OS 附加您的程序时,它会向您传递一个链接堆栈,其中的框架具有指向 SVC 3 指令的 PSW。当您在其他任何事情更改堆栈之前发出 PR 时,您间接地对这条 SVC 3 指令进行了长分支,并且您的程序结束了。
您可以自己验证这一点 - 在程序入口处进行转储,并查看格式化的链接堆栈。如果您不知道如何执行此操作,只需在入口点创建一个带有 DC F'0' 的单行汇编程序,并使用分配的 //SYSMDUMP DD 语句(SYSMDUMP = 机器可读转储)批量运行它。然后,您可以使用 IPCS 以交互方式查看转储并找出所有这些内容(这本身就是一项宝贵的技能!)。