将 JonesForth 移植到 macOS v10.15 (Catalina)



我试图让JonesForth在开箱即用的最新MacBook上运行,只是使用Mac工具。

我开始将所有内容转换为 64 位并注意 Mac 汇编程序语法。

我有东西要组装,但我立即遇到了一个奇怪的分段错误:


/* NEXT macro. */
.macro NEXT
lodsq
jmpq *(%rax)
.endm
...
/* Assembler entry point. */
.text
.globl start
.balign 16
start:
cld
mov %rsp,var_SZ(%rip)           // Save the initial data stack pointer in FORTH variable S0.
mov return_stack_top(%rip),%rbp // Initialise the return stack.
//call set_up_data_segment
mov cold_start(%rip),%rsi       // Initialise interpreter.
NEXT                    // Run interpreter!
.const
cold_start:                     // High-level code without a codeword.
.quad QUIT

QUIT 通过宏 defword 定义如下:

.macro defword
.const_data
.balign 8
.globl name_$3
name_$3 :
.quad $4                // Link
.byte $2+$1             // Flags + length byte
.ascii $0               // The name
.balign 8               // Padding to next four-byte boundary
.globl $3
$3 :
.quad DOCOL             // Codeword - the interpreter
// list of word pointers follow
.endm
// QUIT must not return (ie. must not call EXIT).
defword "QUIT",4,,QUIT,name_TELL
.quad RZ,RSPSTORE       // R0 RSP!, clear the return stack
.quad INTERPRET         // Interpret the next word
.quad BRANCH,-16        // And loop (indefinitely)
...more code

当我运行这个时,我在 NEXT 宏中第一次出现分段错误:

(lldb) run
There is a running process, kill it and restart?: [Y/n] y
Process 83000 exited with status = 9 (0x00000009)
Process 83042 launched: '/Users/klapauciusisgreat/jonesforth64/jonesforth' (x86_64)
Process 83042 stopped
* thread #1, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100000698 jonesforth`start + 24
jonesforth`start:
->  0x100000698 <+24>: jmpq   *(%rax)
0x10000069a <+26>: nopw   (%rax,%rax)
jonesforth`code_DROP:
0x1000006a0 <+0>:  popq   %rax
0x1000006a1 <+1>:  lodsq  (%rsi), %rax
Target 0: (jonesforth) stopped.

rax 确实指出了我认为是取消引用的地址 DOCOL:

(lldb) register read
General Purpose Registers:
rax = 0x0000000100000660  jonesforth`DOCOL

所以一个谜团是:

  1. 为什么 RAX 指向 DOCOL 而不是 QUIT?我的猜测是指令执行了一半,间接寻址的结果存储在 rax 中。有哪些好的文档指针?
  2. 为什么会有分段错误?

我在原始代码中注释掉了调用 brk 以设置数据段的原始段设置代码。另一个[实现]也根本没有调用它,所以我想我也可以忽略它。如何在 Catalina 上的 64 位二进制文件中使用系统调用设置分段权限有什么魔力吗?make命令几乎是标准的JonesForth命令:

jonesforth: jonesforth.S
gcc -nostdlib -g -static $(BUILD_ID_NONE) -o $@ $<

PS:是的,我可以让 JonesForth 在 Docker 镜像中完美运行,但这不是重点。我真的希望它在卡塔琳娜上以 64 位工作,开箱即用。

原始代码有类似的东西

mov $cold_start,%rsi

苹果汇编程序抱怨无法在 32 位二进制文件中使用 64 个即时寻址。

所以我尝试了

mov $cold_start(%rip),%rsi

但这也行不通。

所以我尝试了

mov cold_start(%rip),%rsi

它组装,但当然它会取消引用cold start,这不是我需要的。

这样做的正确方法显然是

lea cold_start(%rip),%rsi

这似乎按预期工作。

相关内容

  • 没有找到相关文章

最新更新