3

10 個の数値を追加するための次のアセンブリ コードを作成しました。コンパイルして実行することはできますが、間違った結果が得られます。合計の値をスクリーンに出力する方法を知りたかっただけです。

section .data
num1: dw 10, 20, 30, 40, 50, 10, 20, 30, 40, 50
total: dw 0
msg :  db "sum=%d",10,0

section .text
    extern _printf
    global _main
_main:
    push ebp
    mov ebp,esp
    mov ebx,num1 ;point bx to first number
    mov ecx,10      ;load count of numbers in ecx
    mov eax,0       ;initialize sum to zero
loop:
    add eax,[ebx]
    add ebx,2
    sub ecx,1
    jnz loop
    mov [total],eax

    push total
    push msg
    call _printf

    pop ebp
    mov esp,ebp
    ret

解決

section .data
num1: dd 10, 20, 30, 40, 50, 10, 20, 30, 40, 50,300
total: dd 0
msg :  dd "sum=%d",10,0

    section .text
        extern _printf
        global _main
    _main:
        push ebp
        mov ebp,esp
        mov ebx,num1 ;point bx to first number
        mov ecx,11     ;load count of numbers in ecx
        mov eax,0       ;initialize sum to zero
    loop:
        add eax,[ebx]
        add ebx,4
        sub ecx,1
        jnz loop
        mov  [total],eax
        push dword [total]

        push msg
        call _printf
        mov esp,ebp
        pop ebp

        ret
4

3 に答える 3

3

ここにはいくつかの問題があります。まず、 を取得しnum1totalとして宣言しましdwた。dw「dword」を意味するように聞こえるかもしれませんが、「データワード」を意味します。これらをdd「data dword」にしたい...それがあなたがそれらを使用している方法だからです。(そしてadd ebx, 42 ではありません) 本当に 32 ビット コードでワード (16 ビット) 値を使用する必要がある場合は、それを行うことができますが、厄介です。

私が見る 2 番目の問題は、 のアドレスをプッシュするpush total前に. ここでメモリの「[コンテンツ]」が必要なので、. (正解です)call _printftotalpush dword [total]push msg

この後、おそらく必要になります(それぞれ 4 バイトの 2 つのパラメーターadd esp, 8として記述するのが好きです)。add esp, 4 * 2このスタックのクリーンアップを「延期」することは可能です-mov esp, ebp修正しますが、前に行う必要がありますpop ebp!!!

...もっとあるかもしれません...

于 2013-01-08T13:58:10.933 に答える
3

16 ビット値を操作するために 32 ビット メモリ アクセスを使用しています。

配列の各要素は 16 ビット幅です。ただし、eaxは 32 ビット幅であるため、次の例では配列を各要素も 32 ビット幅であるかのように扱います。

add eax,[ebx]

以下もまったく同じ理由で正しくありません。

mov [total],eax

を呼び出す前にのアドレスをプッシュしているという問題もあると思いますが、おそらくそのをプッシュする必要があります。totalprintf()

また、@JasonD が指摘したように、呼び出し後にスタックをクリーンアップする必要がありますprintf()

最後に、

mov esp,ebp

命令は、スタック ポインターが破損するだけなので、削除する必要があります。

于 2013-01-08T13:35:24.310 に答える
2

dwは 16 ビット エンティティを定義していますadd eax,[ebx]が、32 ビット エンティティを追加しています。dwddに変更するか、 WORD PTRを[ebx]の前に置きます。また、NPE が指摘しているように、eaxの格納方法をtotalに変更する必要があります。

于 2013-01-08T13:36:07.357 に答える