0

5x5 行列をサブルーチンに渡す NASM アセンブリ プログラムを作成しようとしていますが、このサブルーチンは最大値を返します。私がしていることは、すべての要素をスタックにプッシュし、値を比較するときにそれらを 1 つずつポップすることです。これらの値を取得しようとすると「セグメンテーション違反」エラーが発生しますが、その理由がわかりません


segment .data

        hello db "hello",0xa
        hellol equ $-hello

segment .bss

        largest resw 1
        temp resw 1

        matrix resw 25

segment .text

        global _start

_start:
        ;initializing matrix
        mov [matrix + 0*2],word 50 ;Row 1
        mov [matrix + 1*2],word 52
        mov [matrix + 2*2],word 28
        mov [matrix + 3*2],word 12
        mov [matrix + 4*2],word 9
        mov [matrix + 5*2],word 2 ;Row 2
        mov [matrix + 6*2],word 21
        mov [matrix + 7*2],word 3
        mov [matrix + 8*2],word 124
        mov [matrix + 9*2],word 1
        mov [matrix + 10*2],word 23 ;Row 3
        mov [matrix + 11*2],word 32
        mov [matrix + 12*2],word 55
        mov [matrix + 13*2],word 83
        mov [matrix + 14*2],word 325
        mov [matrix + 15*2],word 321 ;Row 4
        mov [matrix + 16*2],word 1
        mov [matrix + 17*2],word 22
        mov [matrix + 18*2],word 11
        mov [matrix + 19*2],word 2
        mov [matrix + 20*2],word 213 ;Row 5
        mov [matrix + 21*2],word 4
        mov [matrix + 22*2],word 52
        mov [matrix + 23*2],word 83
        mov [matrix + 24*2],word 32


        mov ecx,25 ;Set the loop counter to 25
        mov esi,0 ;set index counter to 0

        pushLoop: ;Push all the elements from matrix onto the stack
                mov eax,[matrix + esi*2]
                push eax
                inc esi
                        loop pushLoop

        call findLargest

        call printLargest ;Not yet implemented, only prints "hello"

exit:
        mov eax,1
        xor ebx,ebx
        int 0x80
;Exit


findLargest: ;Finds the largest number in matrix and stores it in "largest"

        mov ebx,0 ;ebx will store the largest value
        mov ecx,25
        largestLoop:
                pop eax         ;Error is here, Segmentation fault....
                cmp eax,ebx
                jle skip
                mov ebx,eax
                skip:
                        loop largestLoop
        ;End of largestLoop
        mov [largest],ebx

ret
;end of findLargest subroutine

printLargest:
        mov eax,4
        mov ebx,1
        mov ecx,hello
        mov edx,hellol
        int 0x80
ret

エラーが発生した行をコメントアウトすると、プログラムは正常に機能します

助けてくれてありがとう!

4

1 に答える 1

1

なぜ各要素をプッシュしているのですか?マトリックスのアドレスをプロシージャに渡すだけです。

また、これらの要素をプッシュしてから関数を呼び出すと、それらの要素は eax ではなくスタック上にあるため、 になりますesp。スタックは DWORD で整列され、ワー​​ドで整列されません。

それらが使用している値である場合は、配列の値をデータ セクションに設定するだけで済みます。

これで邪魔になりません。最初にすべきこと/試すことは、配列をループして各要素を出力することです。それができたら、変更して最大数をテストします。

segment .data
fmt         db "%d",10, 0
matrix      dd 50, 52, 28, 12, 9, 2, 21, 3, 124, 1, 23, 32, 55, 83
            dd 325, 321, 1, 22, 11, 2, 213, 4, 52, 83, 32
matrix_len equ ($ - matrix) / 4 - 1

segment .text

extern printf, exit
global _start

_start:

    push    matrix
    call    findLargest

    call    exit

findLargest:
    push    ebp
    mov     ebp, esp                        ; array pointer is now in [ebp + 8]

    mov     esi, dword[ebp + 8]             ; pointer to our array
    mov     ebx, matrix_len                 ; loop counter
    mov     edi, 0                          ; 

PrintEm:
    push    dword [esi + edi * 4]           ; print each element in the array = Base pointer + index * scale
    push    fmt
    call    printf
    add     esp, 4 * 2 
    inc     edi                             ; step index
    dec     ebx                             ; decrease loop counter
    jns     PrintEm                         ; if not -1 repeat loop

    mov     esp, ebp
    pop     ebp
    ret     4                               ; pushed 1 dword

わかりました、行列配列をループして、各値を適切に出力します。今それを変更して最大値を見つけます...

ここに画像の説明を入力

于 2013-03-16T19:49:07.473 に答える