1

我正在编写一个 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]

编辑 - 在对二进制文件进行 hexdump 之后,我可以看到上面 b 中的值实际上比编译标签 c 的地址高 0x1000。c 位于 0x00000f43,但 b 包含 0x1f40

4

1 回答 1

0

首先,在至少 32 位的现代 x86 机器上使用 'si' 和 'di' 16 位寄存器看起来非常危险。

尝试使用“esi”和“edi”。当 'xt_bye' 不大于 2^16 时,您可能会很幸运地避免了一些崩溃。

另一件事:在 xt_bye 的末尾没有“RET”。

还有一个:看到这个链接的问题Help with Assembly。在 Mac OS X 上编译样本时出现分段错误

看起来您正在将 ESP 寄存器更改很多,并且它变得未对齐 16 个字节。从而崩溃。

还有一个:

jmp [di]

可能无法加载正确的地址,因为未使用 DS/ES reg,因此 0x1000 偏移量。

于 2012-05-29T10:37:38.287 回答