0

少し前に Assembly (NASM フレーバー) に手を出しましたが、もう一度学ぼうとしています。(最初に文字列の長さを数えることができることは知っていますが、それは演習です)

とにかく、私はこのコードを書いて、null で終了する文字列をstdoutusingに出力しsys_writeました。(私はそれを一般化するつもりです、私はちょうど今テストしています。)

i呼び出す前にインクリメントすると がsys_write出力され'e'ますが、後でインクリメントすると'H'期待どおりに出力されるため、機能するようです。ただし、 が検出されるとすぐにjne print_loop、エラー コード の実行時エラーが生成されます-1。いくつかのジャンプ命令を試してみましたが、すべてクラッシュしましたが、ジャンプを削除するとすぐに、プログラムはエラーなしで実行されます。

イデオネ

SECTION .data
    hello:
        db "Hello World!/n",0

SECTION .bss
    i: 
        resb 1

SECTION .text
    global _start

    _start:
        mov ecx, hello
        call print

        mov eax, 1
        mov ebx, 0
        int 80h

    print:
        mov eax, 4
        mov ebx, 1
        mov edx, 1

        print_loop:
            push eax
            mov eax, [i]
            lea ecx, [ecx+eax]
            pop eax

            int 80h
            inc dword [i]
            cmp ecx, 0  
            jne print_loop ; if I comment this out, it runs without error.

        ret

修正版は次のとおりです。

%macro print_ 1
    mov eax, 4
    mov ebx, 1
    mov ecx, %1

    call print
%endmacro

%macro exit_ 1
    mov eax, 1
    mov ebx, %1
    int 80h
%endmacro

SECTION .data
    hello:
        db "Hello World!/n",0

SECTION .bss
    i: 
        resb 1

SECTION .text
    global _start

    _start:
        print_ hello
        exit_ 0

    ;print code called by print_ macro
    print:
        push ecx
        count:
            inc ecx
            cmp byte [ecx], 0
            jne count

        mov edx, ecx
        pop ecx
        sub edx, ecx

        int 80h
    ret
4

2 に答える 2

1

コードにはいくつかの問題があります。

i: 
    resb 1

ここでは 1 バイトのスペースを予約しますが、印刷機能でiは dword として扱います。

int 80h

syscall の戻り値が保持されるeaxため、これは の古い値を破棄します。したがって、反復ごとにシステムコール番号 (4)eaxをリロードする必要があります。eax

lea ecx, [ecx+eax]

ここでは、文字列のベース アドレスを で上書きします&string[i]。これにより、元の値が保持されないため、後続の反復でアドレスが正しくなくなりecxます。

cmp ecx, 0

なぜあなたecxが 0 になると予想するのかわかりません。格納されているバイトをロードし、それ[ecx]をゼロと比較する方が理にかなっています (syscall の前に)。

于 2013-03-28T18:01:49.177 に答える
0

いくつかの問題。

初め:

  mov eax, [i]

iはバイト変数ですが、命令はその位置から 4 バイトを読み取ります。

  inc dword [i]

iはバイト変数ですが、命令はその位置で 4 バイトの値をインクリメントします。

2番目(と思います):

ecxこの指示の後に何が起こるか

  lea ecx, [ecx+eax]

2回目の実行?を指している有効なアドレスになりhelloますか?

ところで、デバッガの使い方を学びましょう。そろそろですね。

于 2013-03-28T17:55:59.453 に答える