2

几个月来,我一直在尝试为我的 Ti-89 构建一个自制的 B 交叉编译器,最终我想生成我的计算器执行的程序集。该语言是“B”,因为只有一种类型是整数/指针。我不明白如何在这个平台上实现函数指针。我正在考虑通过以下方式实现函数指针:

  • 使用立即值存储第一条指令的地址
  • 使用程序计数器和偏移量推导第一条指令的地址
  • 仅存储偏移量并计算跳转时第一条指令的地址。

第一种方法肯定行不通,因为 Ti-89 上的汇编程序在执行之前会被复制到 RAM 中。我无法在编译时知道函数的位置。此外,根据第 24 页的 Ti-89/Ti-92 Plus 开发人员指南,“ASM 程序可能会在堆垃圾收集期间移动。指向覆盖系统代码的指针将变得无效。” 这意味着第二种方法也不一定有效,因为堆垃圾收集可能发生在计算第一条指令的地址之后。假设它所说的程序移动是正确的,这可能会导致整个函数移动。第三种方法将在特定情况下起作用,但问题是我不一定知道该函数将在汇编程序中的哪个位置被调用。

TIGCC 允许使用函数指针,那么它们到底是如何实现它们的呢?有什么我想念的吗?

链接:

4

2 回答 2

3

如果要在同一编译单元中获取函数的地址,则应使用 PC 相对寻址。您可以使用lea(load Effective address) 将地址存储在任何地址寄存器中(a0- a6。从技术上讲,a7也可以,但不要那样做。a6也经常保留为帧指针):

lea   myfunc(PC),a2

这可以使用jsr (a2)(jump to subroutine) 调用,或者在某些情况下仅使用jmp (a2)(本质上是尾部跳转,以防堆栈上的参数已经与 预期的函数参数匹配myfunc)。

或者,您可以使用pea(push effective address) 将地址压入堆栈:

pea   myfunc(PC)

这可以是函数参数,或者如果它位于堆栈顶部,您将使用 next 跳转到该地址rts。例如,如果你有一个这样结束的函数:

    lea  myfunc(PC),a2
; some other code (not changing a2, not messing with the stack)
    bsr  foo   ; local subroutine
    jsr  (a2)
    rts

你也可以写:

    pea  myfunc(PC)
; some other code (not messing with the stack)
    bra  foo  ; tail call to local subroutine foo
              ; on return this will jump to myfunc
              ; when myfunc ends, it returns to the caller of this function
于 2019-02-24T20:50:00.060 回答
0

我听从了@lurker 的建议。该程序集似乎只是将地址推入堆栈而没有更多信息。通过测试,如果我的函数被命名,my_func那么程序集看起来就像move.l #my_func,-4(%fp)只是在推动函数指针。我猜汇编器会将其转换为推送 PC 的直接相对地址,而不仅仅是二进制文件中的实际地址。这意味着我读错了我之前引用的文档。我认为它想说的是你不能引用内存中二进制文件中的地址,但你可以指的是它放在 RAM 中的临时副本中的地址。这将更有意义,因为操作系统不会真正在后台运行,而汇编程序仍然运行。我不得不假设垃圾收集是只有在程序执行后才能发生的事情。

于 2019-02-24T01:53:37.670 回答