1

私は Forth の内部インタープリターを作成していて、最も単純な部分で行き詰まっています。Mac で NASM を使用する (マッチョ)

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]

編集 - バイナリを 16 進ダンプした後、上記の b の値が実際には、ラベル c がコンパイルされたアドレスよりも 0x1000 高いことがわかります。c は 0x00000f43 ですが、b には 0x1f40 が含まれています

4

1 に答える 1

0

まず、少なくとも32ビットである最新のx86マシンで「si」および「di」16ビットレジスタを使用することは非常に危険に見えます。

「esi」と「edi」を使用してみてください。'xt_bye'が2^16以下の場合、クラッシュの一部を回避できれば幸いです。

もう1つは、xt_byeの最後に「RET」がないことです。

もう1つ:このリンクされた質問「アセンブリのヘルプ」を参照してください。MacOSXでサンプルをコンパイルする際のセグメンテーション違反

ESPレジスタを大幅に変更しているようで、16バイトだけ整列されなくなります。したがって、クラッシュ。

もう1つ:

jmp [di]

DS / ES regが使用されていないため、正しいアドレスがロードされない可能性があります。したがって、0x1000オフセットです。

于 2012-05-29T10:37:38.287 に答える