【发布时间】:2012-05-29 10:27:39
【问题描述】:
我正在编写一个 Forth 内部解释器,却陷入了应该是最简单的部分。在 Mac 上使用 NASM (macho)
msg db "k thx bye",0xA ; string with carriage return
len equ $ - msg ; string length in bytes
xt_test:
dw xt_bye ; <- SI Starts Here
dw 0
db 3,'bye'
xt_bye dw $+2 ; <- Should point to...
push dword len ; <-- code here
push dword msg ; <--- but it never gets here
push dword 1
mov eax, 0x4 ; print the msg
int 80h
add esp, 12
push dword 0
mov eax, 0x1 ; exit(0)
int 80h
_main:
mov si,xt_test ; si points to the first xt
lodsw ; ax now points to the CFA of the first word, si to the next word
mov di,ax
jmp [di] ; jmp to address in CFA (Here's the segfault)
运行时出现 Segmentation Fault: 11。作为测试,我可以将 _main 更改为
_main:
mov di,xt_bye+2
jmp di
它可以工作
编辑 - 这是我正在尝试做的最简单的可能形式,因为我认为那里有一些红鲱鱼:)
a dw b
b dw c
c jmp _my_actual_code
_main:
mov si,a
lodsw
mov di,ax
jmp [di]
EDIT - 对二进制文件进行十六进制转储后,我可以看到上面 b 中的值实际上比标签 c 编译的地址高 0x1000。 c 在 0x00000f43,但 b 包含 0x1f40
【问题讨论】:
-
也许你应该发布完整的源代码? msg,_syscall(只是“int 0x80”吗?)
-
对 - _syscall 只是 int 80h,唯一缺少的是 msg 和 len,我会去修复 :)
-
看起来这与段寄存器有关。 0x1000 偏移量可能来自 DS=0x100 之类的。抱歉,我只有一台旧的 PowerPC G5 mac,所以我无法准确测试您的 x86 asm :)
-
非常感谢您对此提供的帮助,Viktor - 它可能假定 DS 而不是 CS,这是有道理的 - 我会试一试并告诉您。
-
当然,所有这些漂亮的装配难题让我想起了很多过去 :) 很高兴能提供帮助 :)