Assembly Ti-89 68k组件中的函数指针
几个月来,我一直在尝试为我的Ti-89构建一个自制的brew B交叉编译器,现在终于到了我想要生成计算器执行的程序集的时候了。语言是“B”,因为只有一种类型是整数/指针。我不明白如何在这个平台上实现函数指针。我考虑通过以下方式实现函数指针:Assembly Ti-89 68k组件中的函数指针,assembly,compiler-construction,68000,b,Assembly,Compiler Construction,68000,B,几个月来,我一直在尝试为我的Ti-89构建一个自制的brew B交叉编译器,现在终于到了我想要生成计算器执行的程序集的时候了。语言是“B”,因为只有一种类型是整数/指针。我不明白如何在这个平台上实现函数指针。我考虑通过以下方式实现函数指针: 使用立即数值存储第一条指令的地址 使用程序计数器和偏移量导出第一条指令的地址 仅存储偏移量并在跳转时计算第一条指令的地址 第一种方法肯定行不通,因为Ti-89上的汇编程序在执行之前会复制到RAM中。我无法在编译时知道函数将位于何处。此外,根据第24页的T
- 使用立即数值存储第一条指令的地址
- 使用程序计数器和偏移量导出第一条指令的地址
- 仅存储偏移量并在跳转时计算第一条指令的地址
- Ti-89/Ti-92开发者指南:
- TIGCC:
- 我的项目:
my_func
,则程序集看起来像是move.l\my_func,-4(%fp)
,它只是在按函数指针。我猜汇编器会将其转换为PC机的直接相对地址,而不仅仅是二进制文件中的实际地址。这意味着我之前引用的文档读错了。我想它想说的是,你不能引用内存中二进制文件中的地址,但你可以引用内存中临时副本中的地址。这将更有意义,因为无论如何,当汇编程序运行时,操作系统不会真正在后台运行。我必须假设垃圾收集只能在程序执行后发生。如果要获取同一编译单元中函数的地址,应该使用PC相对寻址。您可以使用lea
(加载有效地址)将地址存储在任何地址寄存器中(a0
-a6
。从技术上讲,a7
也可以工作,但不要这样做。a6
通常也被保留为帧指针):
可以使用jsr(a2)
(跳转到子例程),或者在某些情况下仅使用jmp(a2)
(如果堆栈上的参数已经与myfunc
所期望的函数参数匹配,则本质上是尾部跳转)来调用它
或者,您可以使用pea
(推送有效地址)在堆栈上推送地址:
pea myfunc(PC)
这可以是一个函数参数,或者如果它位于堆栈的顶部,您将使用下一个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
TIGCC是否支持gcc的-s选项来输出Ti-89组件?@Lowerer是的,它支持!酷。您可以编写使用函数指针的最简单的C程序,并查看
-S
选项为您提供了什么。是否希望函数指针指向系统函数,指向不同编译单元或相同编译单元中的函数?@chtz我需要一个指向相同编译单元的函数指针——可能是您在禁用优化的情况下编译的,否则它不需要将函数指针存储在堆栈上(取决于您对它所做的操作)。无论如何,不,它可能正在使用带有绝对地址的mov
-立即数(由链接器填写和/或修复运行时)。TIGCC如何访问静态数据,例如将static int foo
的地址传递给extern void bar(int*)
函数?@Peter Cordes Yes,编译优化级别-O0
。当我进行测试时,编译器在可执行文件的末尾为变量保留空间,并用pea foo
加载指针,这对于将foo的地址推送到堆栈上来说只有68k。我将反汇编二进制文件,以确保它没有使用PC间接寻址。如果你可以使用即时地址,你要么有一个重新定位的加载程序,要么你的汇编程序将所有内容转换为PC相对地址。两者都是可能的。如果可执行文件在执行过程中像文档中所说的那样移动,这会中断,不是吗?我将其重新解释为,存储的可执行文件可以移动,但不能移动正在运行的RAM中的副本。如果可执行文件在“执行期间”移动,则会出现更大的问题。我为TI-92+编程已经有一段时间了,但这永远不会发生。PC相对寻址的最大优点是,内核在启动之前不需要计算任何绝对地址。这对于跳转到不超过+-32767字节的子例程非常有效,甚至可以用于“移动代码”(我认为TI上不会发生这种情况)如果您可以确保它不会在寄存器负载和实际跳转之间移动。
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