Вызовы функций x86-64 с использованием ошибки отладки стека GDB не могут получить доступ к памяти в местоположении ххх - PullRequest
0 голосов
/ 21 февраля 2019

Я пишу программу, вызывающую 2 предварительно заданные функции min.c и conv.c, также, конечно, main.c min.s выглядит следующим образом:

.file   "min.c"
    .text
    .p2align 4,,15
    .globl  min
    .type   min, @function
min:
.LFB0:
    .cfi_startproc
    cmpl    %esi, %edi
    movl    %esi, %eax
    cmovle  %edi, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   min, .-min
    .ident  "GCC: (Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0"
    .section    .note.GNU-stack,"",@progbits

conv.c:

char conv(char *, char *, int);

char conv(char *x, char *h, int n) {
    char ret = 0;
    int i;
    for (i = 0; i < n; i++) {
        ret += x[i] * h[n-i-1];
    }
    return ret;
}

min.c:

int min(int, int);

int min(int a, int b) {
    if (a < b) return a;
    return b;
}

и conv.s идет следующим образом:

.file   "conv.c"
    .text
    .p2align 4,,15
    .globl  conv
    .type   conv, @function
conv:
.LFB0:
    .cfi_startproc
    testl   %edx, %edx
    jle .L4
    movslq  %edx, %rax
    leaq    -1(%rsi,%rax), %rcx
    leaq    -2(%rsi,%rax), %rsi
    leal    -1(%rdx), %eax
    xorl    %edx, %edx
    subq    %rax, %rsi
    .p2align 4,,10
    .p2align 3
.L3:
    movzbl  (%rdi), %eax
    subq    $1, %rcx
    addq    $1, %rdi
    mulb    1(%rcx)
    addl    %eax, %edx
    cmpq    %rcx, %rsi
    jne .L3
    movl    %edx, %eax
    ret
    .p2align 4,,10
    .p2align 3
.L4:
    xorl    %edx, %edx
    movl    %edx, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   conv, .-conv
    .ident  "GCC: (Ubuntu 7.4.0-1ubuntu1~16.04~ppa1) 7.4.0"
    .section    .note.GNU-stack,"",@progbits

также мой маленький основной кусок кода пытается просто пойтипосле предварительно заданного алгоритма:

    for i from 0 to n+m-2 do
ladj <- min(i+1, m)
radj <- m - min(m+n-(i+1), m)
result[i] <- conv(x + (i+1-ladj), h + radj, ladj-radj)

, поэтому я написал:

    .globl conv_arr
    conv_arr:
        movq $0, %rax       # zero out the result

        movq $0, %rbx       # %rbx is set to 0 to be the counter for the loop, i.e. int i

        addq %rsi, %rbp
        addq %rcx, %rbp
        subq $2, %rbp       # 3 lines of code to set a limit for the counter, i.e. n + m - 2

    loop: # loop label
        cmpq %rbx, %rbp     # comparing to keep the loop in scope from i = 0 to n + m - 2

        jle return      # jump to return label if the counter reaches the limit

        pushq %rdi
        pushq %rsi      # saving all the registers before calling function min( int, int)

        movq %rbx, %r10     # copying the value of %rbx into the value of %r10

        addq $1, %r10       # adding 1 to the value of %r10

        movq %r10, %rdi     # changing the value of %rdi ( in this case the first parameter
                    # to the function min() ) to i + 1

        movq %rcx, %rsi     # changing the value of %rsi ( in this case the second parameter to
                    # the function min() ) to m

        call min        # calling the function min() with the two parameters %rdi, %rsi

        popq %rsi       
        popq %rdi       # restoring the values of %rdi and %rsi to their initial values

        movq %rax, %r12     # copying the value of the result from function min() to %r12,
                    # the register which is now set up to be the value of ladj

        pushq %rdi
        pushq %rsi      # saving the values of %rdi and %rsi before calling function min()

        movq %rcx, %rdi     # copying the value of %rcx ( int m ) into the value of %rdi

        addq %rsi, %rdi     # adding the value of %rsi ( int n ) into the value of %rdi

        subq %rbx, %rdi     # subtracting the value of %rbx ( int i ) from the value of %rdi

        subq $1, %rdi       # subtracting 1 from the value of %rdi

        movq %rcx, %rsi     # copying the value of %rcx ( int m ) into the value of %rsi

        call min        # calling the function min() with two parameters %rdi, %rsi

        popq %rsi
        popq %rdi       # restoring the values of %rdi and %rsi to their initial values

        movq %rcx, %r13     # copying the value of %rcx ( int m ) into the value of 

                    # register %r13

        subq %rax, %r13     # subtracting the value of %rax ( min( m + n - ( i + 1 ), m ) )
                    # from the value of %rcx ( m )

        movq %r13, %r14     # copying the value of %r13 ( m - min( m + n - ( i + 1 ), m )                   # ) into the value of %r14, the register which is now set up 
                    # to be the value of radj

        pushq %rdi
        pushq %rsi      
        pushq %rdx
        pushq %rcx      # saving the values of %rdi, %rsi, %rdx and %rcx before calling 
                    # function conv( char*, char*, int )

        addq %rbx, %rdi     # adding the value of %rbx ( i ) to the value of %rdi ( char* x )

        addq $1, %rdi       # adding 1 to the value of %rdi

        subq %r12, %rdi     # subtracting the value of %r12 ( ladj ) from the value of %rdi

        movq %rdx, %rsi     # copying the value of %rdx ( char* h ) to the value of %rsi

        addq %r14, %rsi     # adding the value of %r14 ( radj ) to the value of %rsi

        movq %r12, %rdx     # copying the value of %r12 ( ladj ) to the value of %rdx

        subq %r14, %rdx     # subtracting the value of %r14 ( radj ) from the value of %rdx

        call conv       # calling the function conv() with three parameters %rdi, %rsi
                    # and %rdx

        popq %rcx
        popq %rdx
        popq %rsi
        popq %rdi       # restoring the values of %rdi, %rsi, %rdx and %rcx to their                    # initial values

        movq %rax, %r8      # copying the value of %rax ( result after calling function conv()                  # ) into the value of the index that %r8 ( char* result) is                     # pointing to

        incq %rbx       # incrementing the value of %rbx ( i ) by 1

        incq %r8        # incrementing the value of %r8 ( char* result ) according to the
                    # value of %rbx ( i ), i.e. result[i]

        jmp loop        # jump back to the loop label when all the procedures are done

    return: # return label
        ret

все комментарии даны для отслеживания того, что я пытался сделать, я знаю, что это нужномного больше исследований и внимания.Когда я запустил программу, это дало ошибку сегментации, я запустил GDB с ним, и он говорит, что ошибка не может получить доступ к памяти по адресу xxx:
Программа получила сигнал SIGSEGV, Ошибка сегментации.

0x0000000000400757 in conv (x=0x601050 <signal> "",
      h=0xffffffff80601050 <error: Cannot access memory at address 0xffffffff601050> n=15) at conv.c:8.

8                ret += x[i] * h[n-i-1];

Iпробовал точки останова в строках, используя conv.c, и при подсчете он возвращался назад, т. е. когда программа достигала n = 3, он начинал возвращаться к n = 2, n = 1, а затем еще дальше к n = -12 и далее.

**** Если бы у кого-нибудь были какие-то предложения, я бы действительно оценил это ****.

...