【问题标题】:Leaf functions in SPARC and HP-UXSPARC 和 HP-UX 中的叶函数
【发布时间】:2011-03-30 20:30:57
【问题描述】:

我刚刚阅读了一篇在 HP-UX 中进行反汇编的 Phrack 文章。我读到有两类功能可以在 HP-UX 和 SPARC 下使用;叶函数和非叶函数。以下是我从here 截取的反汇编部分。

(gdb) disass leaf
Dump of assembler code for function foo:
0x3280 <leaf>:           copy r3,r1
0x3284 <leaf+4>:         copy sp,r3
0x3288 <leaf+8>:         stw,ma r1,40(sr0,sp)
0x328c <leaf+12>:        stw r26,-24(sr0,r3)
0x3290 <leaf+16>:        stw  r0,8(sr0,r3)
0x3294 <leaf+20>:        ldi 1,r19
0x3298 <leaf+24>:        stw  r19,8(sr0,r3)
0x329c <leaf+28>:        ldo 40(r3),sp
0x32a0 <leaf+32>:        ldw,mb -40(sr0,sp),r3
0x32a4 <leaf+36>:        bv,n r0(rp)
End of assembler dump.
(gdb)

通常在调用函数时,返回地址会被压入堆栈,以便程序在函数执行完成后知道将控制权返回到哪里。在这些叶子函数的情况下它是如何工作的?

我没有任何 HP-UX/SPARC 机器的访问权限,因此无法自己尝试(而且由于同样的原因,我也不太了解这种情况下的程序集)。

有人可以解释在这种情况下控制如何返回到被调用函数吗?

【问题讨论】:

    标签: gdb disassembly sparc hp-ux


    【解决方案1】:

    首先,您链接到的文档和您显示的代码不是 Sparc,而是 PA-RISC,这是一种独特的架构。据我所知,没有任何版本的 HP/UX 可以在基于 Sparc 的系统上运行。

    尽管如此,关于叶函数的观点在许多架构中都是相似的,包括 Sparc、PA-RISC、PowerPC、ARM、MIPS……事实上所有的 RISC 架构。对于所有这些,执行函数调用的操作码不会将返回地址存储在堆栈中;事实上,没有硬件所知道的“真正的”堆栈。相反,使用特定寄存器作为堆栈指针只是一个软件约定。调用操作码将返回的地址存储在一个特定的寄存器中,通常称为“链接寄存器”。从函数返回的操作码只是读取该寄存器。

    如果函数本身(我们称它为 A)调用另一个函数(B),那么该嵌套调用也将使用链接寄存器;但是,A 在返回时将需要链接寄存器的内容。因此,A 必须将链接寄存器保存在某个地方,通常是在内存中,更准确地说,是在通常用作“堆栈”的内存区域中。

    叶函数是不调用其他函数的函数;它只是完成它的工作并返回。叶函数不需要将链接寄存器保存在堆栈中,因为不会改变链接寄存器的内容。

    另外一个也是常规的限制是关于堆栈帧结构。某些操作系统,在某些架构上,坚持以非常特定的方式使用堆栈的功能(称为“堆栈帧”),调试器可以可靠地探索。然后,规范要求将返回地址保存在堆栈上的精确槽中,并且被调用的函数必须在其执行的早期执行此操作。然后,相同的操作系统可能会声明这对于叶函数不是绝对必需的(如果该函数不调用其他函数,则调试器更容易处理无帧函数,即没有帧被压入堆栈之上缺少的一个)。不设置堆栈帧比设置堆栈帧更有效(在执行速度和代码大小方面),因此出现异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多