assembly X86程序集-将数组传递到函数的分段故障?

wlp8pajw  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(117)

使用GDB,我看到了当它执行“call Mby5”时分段错误发生的地方,但即使调试它,我也不明白为什么当我调用函数时它会得到分段错误?
在这段代码中,我有两个数组,第一个我打印到屏幕上,然后第二个“ard2”我想把第一个的值乘以5,然后把这些新值存储在“ard2”中,然后打印它们。Mby5函数是我试图把它们相乘并把新值存储在ard2中的地方,然后返回并调用PrintArray。这里是完整的代码,并将附上GDB的屏幕截图,显示错误何时发生。

section .data 
    msg1: db 'Here are the array element values: ',10, 0 
    msgL1: equ $-msg1

    msg2: db"Here are the new array element values after multiplying by 5! ",10, 0
    msgL2: equ $-msg2

    ard1: dd 2, 4, 6, 8, 10, 20, 40
    ard1L: equ ($-ard1) / 4 ; Number of elments = array length / 4

    ard2: dd 0, 0, 0, 0, 0, 0, 0
    ard2L: equ ($-ard2) / 4 ; Number of elments = array length / 4

section .text 
    global _start ; declare _start as a global label
_start:
    push ebp        ; save ebp for whoever called main function (OS or other program)
    mov ebp, esp    ; create our new stack frame

   mov ecx,msg1 ; print message #1
   mov edx,msgL1
   call PString

   ;save array base address in ebx and save size of the array in ecx
   mov ebx, ard1
   mov ecx, ard1L

   ;call PrintArray to print the array element
   call PrintArray

   ;print message2
   mov ecx, msg2
   mov edx, msgL2
   call PString

   ;restore the array address and its size to the stack before calling Mby5 function
   mov ebx, ard1
   mov ecx, ard1L
   call Mby5  **[ERROR HAPPENS WHEN I CALL IT HERE]**
    
  ;After multplfying array1 elements by 5 and storing it in ard2 we call PrintArray and pass it ard2
  mov ebx, ard2
  mov ecx, ard2L

  ;Call PrintArray 
  call PrintArray

PrintArray:
    section .text
        push ebp 
        mov ebp, esp

top:
    mov eax,[ebx] ;move the value of [ebx] to eax
    call printDec
    call println
    add ebx, 4
    loop top

    mov esp, ebp ; destroy the stack
    pop ebp
    ret

Mby5:  
    section .text
      push ebp
      mov ebp, esp

top1:
    mov eax, [ebx] ; access first array element. Move its value to eax
    shl eax, 2 ; multiply by 4
    add eax, [ebx] ; multiply by 5
    mov [ard2 + ebx - ard1], eax ; store the result in array2
    add ebx, 4
    loop top1

    popa ;restore registers
    ret

println:
    section .data
    nl db"", 10 
    section .text
        ;save register values of the called function
        pusha
        mov ecx, nl
        mov edx, 1
        mov eax, 4
        mov ebx, 1
        int 80h

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

PString:
    ;Save register values of 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

printDec:
    section .bss
        decstr resb 10;
        ct1 resd 1

    section .text
        pusha ;save all registers

        mov dword[ct1], 0 ; assume initially 0
        mov edi, decstr ;edi points to dec-string in memory
        add edi, 9 ;moved to the last element of string
        xor edx, edx

whileNotZero:
        mov ebx, 10 ;get ready to divide by 10
        div ebx ;divide by 10
        add edx,'0' ; convert to ascii char
        mov byte[edi], dl ; put it in string
        dec edi ;move to next char in string
        inc dword[ct1]
        xor edx, edx ;clear edx
        cmp eax, 0 ;is remainder 0
        jne whileNotZero ; keep looping

        inc edi ; conversion finish
        mov ecx, edi
        mov edx, [ct1]
        mov eax, 4
        mov ebx, 1
        int 0x80

        popa ;restore registers
        ret

错误图片

已使用GDP逐步检查寄存器值。似乎找不到问题。
我改变了Mby5但使用离开和ret

Mby5:
    push ebp
    mov ebp, esp

    mov edi, 0 ; index variable
top1:
    mov eax, [ebx] ; access first array element. Move its value to eax
    shl eax, 2 ; multiply by 4
    add eax, [ebx] ; multiply by 5
    mov [ard2 + ebx - ard1], eax ; store the result in array2
    add ebx, 4
    loop top1

    leave ; restore the original stack frame before returning
    ret

但是我的输出是

Here are the new array element values after multiplying by 5! 
10
20
30
40
50
100
200
10
0
825360384
2356
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
zsh: segmentation fault
xfb7svmp

xfb7svmp1#

如果您从Mby5中“隐藏”与堆栈无关的指令,则仍然是:

push ebp
mov ebp, esp

...

popa ;restore registers
ret

显然popa没有被适当数量的压入字节匹配。这导致调用地址在到达ret之前就被从堆栈中删除,因此调用返回到一个可疑的地址。
你可以通过调整push和pop指令来解决这个问题,比如:

push ebp
pusha
...
popa
pop ebp
ret

或者只是

pushad
...
popad

相关问题