Ошибка сегментации Core Dumped X86 Assembly Array - PullRequest
0 голосов
/ 10 ноября 2018

Раньше я просила помощи и думала, что свободна дома, но я нет. Моя логика была неправильной, и я сильно изменил ее. Эта программа должна возвращать Max int в массиве (который также является последним элементом). Проследив его с помощью GDB несколько раз, я вижу, что попадаю на 5-й (от 2-го до последнего) элемента в массиве «20», когда сталкиваюсь с ошибкой сегментации и программа останавливается. Я установил для ECX длину массива и вычел 1 из ECX, чтобы избежать этого, но моя логика явно неверна. Я ошибаюсь в зависимости от счетчика ECX для завершения цикла. Есть идеи, пожалуйста?

*** РЕДАКТИРОВАТЬ ОСНОВНЫЕ РЕДАКТИРОВАТЬ В КОДЕКС

SECTION .data   ;data section
msg1: db "Here are the array elements:", 10, 0
msg1Len: equ $-msg1
msg2: db "Here is the sorted array:", 10, 0
msg2Len: equ $-msg2



arr: dd 12, 16, 6, 18, 10, 40, 30
arrLen: equ ($-arr)/4   ;number of elements = array length / 4

SECTION .bss
max resd 1 ;declare and reserve space for max


SECTION .text

    global bsort
bsort:
    push ebp ; save old ebp register
    mov ebp, esp ; build a new stack
restart:
    mov ebx, arr ; the base address argument is saved in ebx register
    mov ecx, arrLen ; the size argument is saved in exc register
    sub ecx, 1 ; Last member has no following element to compare with.
    ; So we need to reduce the counter by 1
top:
    mov eax, [ebx] ;; access first array element. Move its value to eax
    cmp eax, [ebx+4] ; compare the value of eax ([ebx]) with [ebx+4]
    jle noswap ; if value at eax is less or equal to value of [ebx+4]
    ; no need to exchang values. Jump to noswap
    xchg eax, [ebx+4] ; if value at eax > value [ebx+4], exchange
    mov [ebx], eax ; store the new exchanged value at [ebx]
    jmp restart ; reset the base address and counter. Start over
noswap:
    add ebx, 4 ; move to the next array element
    loop top ; loop back to the top if the register ecx > 0
    leave
    ret

global main
main:
        push ebp
        mov ebp, esp

        mov ecx, msg1   ;print msg1
        mov edx, msg1Len
        call PString

        ;save array base address in ebx and save sizein in ecx
        mov ebx, arr
        mov ecx, arrLen; store num elements in ecx
        ;loop to print array
PrintArray:
        mov eax, [ebx] ;move value [ebx] to eax
        call PrintDec
        call Println
        add ebx, 4
        loop PrintArray

;call bubblesort
    call bsort

    mov ecx, msg2
    mov edx, msg2Len
    call PString

    ;save arr base add in sbx and size in ecx
    mov ebx, arr
    mov ecx, arrLen
PrintSortedArray:
    mov eax, [ebx]
    call PrintDec
    call Println
    add ebx, 4
    loop PrintSortedArray 

        ;exit program and clean stack
        mov esp, ebp
        pop ebp
        ret

PString:; save register values of the called function
    pusha
    mov eax,4 ; use 'write' system call = 4
    mov ebx,1 ; file descriptor 1 = STDOUT
    int 80h ; call the kernel

    ; restore the old register values of the called function
    popa
    ret

Println:
    ;will call PString func
    ;will change content of ecx and edx
    ;need to save registers used by the main program
    section .data
    nl db 10
    section .text
    pusha

    mov ecx, nl
    mov edx, 1
    call PString

    ;return original register values
    popa
    ret

PrintDec:
;saves all registers so they return unmodified
;build the function to handle dword size

    section .bss
    decstr resb 10 ; 10 32-bit digits
    ct1 resd 1 ;keep track of dec-string size

    section .text
    pusha; save registers

    mov dword[ct1],0 ;initially assume 0
    mov edi, decstr ; edi points to dec-string
    add edi, 9 ; moved to the last element of string
    xor edx, edx ; clear edx for 64-bit div
whileNotZero:
    mov ebx, 10 ; get ready to divide by 10
    div ebx ; divide by 10
    add edx, '0' ; convert to ascii
    mov byte[edi], dl ; put it in string
    dec edi ; move to next char in str
    inc dword[ct1] ; inc char counter
    xor edx, edx ; clear edx
    cmp eax, 0  ;is remainder 0?
    jne whileNotZero ;if no, keep on looping

    inc edi ; conversion finished, bring edi
    mov ecx, edi ; back to start of string. make ecx
    mov edx, [ct1] ; point to counterm edx gets # chars
    mov eax, 4 ; print to stdout
    mov ebx, 1
    int 0x80 ; call kernel

    popa ; restore registers
    ret
...