subq $ 8%rsp分段错误

时间:2016-09-24 13:50:47

标签: assembly segmentation-fault

我正在学习在Linux(gcc)上的x86-64程序集(AT& T)中进行编码,并且在这个简单的代码中无法找到我的分段错误的解决方案。我见过一些关于堆栈对齐的问题;然而,即使我尝试8美元或16美元,这也会失败:

student.h

我写的其他程序似乎在调用printf后工作正常。上面的代码有什么问题?无论有没有退出调用,代码都会失败。这和下面的代码失败了。我使用编译:

.global main
main:

    #prologue
    movq    %rsp, %rbp  #initialise base pointer

    #reserve memory for subroutine
    subq    $8, %rsp   #the line causing the segfault

exit:
    movq    $0, %rdi
    call    exit

整个代码:

gcc -o test test.s

使用(gdb)x / i $ pc时的主代码错误:

.text
formatStr: .asciz "%ld"
resultStr: .asciz "The result is: %d\n"
q1: .asciz "Enter the base: "
q2: .asciz "Enter the exponent: "

#qTable2: #look up table for correct string during scanf
#   .asciz q1
#   .asciz q2

qTable: #alternative look up table
    .quad base
    .quad exponent

    base:
        movq $q1, %rdi
        ret
    exponent:
        movq $q2, %rdi
        ret

###################
# Subroutine:   pow
# Function: Power an integer base to an exponent
# Inputs:   uint base, int exponent(natural)
# Outputs:  int result
##################
pow:
    #prologue
    pushq   %rbp    #store caller base pointer
    movq    %rsp, %rbp

    movq    $1, %rax    #reset result
    movq    $0, %rbx    #initialise loop    
    loop1:
        imulq   %rdi
        incq    %rbx
        cmp %rsi, %rbx  #compare loop interator to exponent
        jle loop1           

    #epilogue
    movq    %rbp, %rsp  #clear local variables from stack
    pop %rbp    #restore caller base pointer
    ret

.global main
###################
# Subroutine:   Main
# Function:     Application entry point
###################

main:

    #prologue
    pushq   %rbp
    movq    %rsp, %rbp  #initialise base pointer

    #reserve memory for subroutine
    subq    $8, %rsp

    #Gather the inputs from the user
    movq    $0, %rbx    #loop counter

#inputAcq:
    #Call printf using correct question
    movq    %rax, %rsi  #move result into argument 2
    movq    qTable(,%rbx,8), %rdi   #format string as argument 1
    call    *%rdi
    movq    $0, %rax    #no vector registers
    call    printf

    leaq    -16(%rbp,%rbx,8), %rsi  #Argument 2 
    movq    formatStr, %rdi #Argument 1
    movq    $0, %rax    #no vector registers
    call    scanf       

    incq    %rbx    #increment loop counter

    cmp $1, %rbx    #check if more inputs are necessary else continue
    jl  inputAcq

    #Call pow
    movq    -8(%rbp), %rsi  #the exponent
    movq    -16(%rbp), %rdi #the base
    call    pow

    #Call printf
    movq    %rax, %rsi  #move result into argument 2
    movq    $resultStr, %rdi    #format string as argument 1
    movq    $0, %rax    #no vector registers
    call    printf

#exit program without errors
exit:
    movq    $0 , %rdi
    call    exit

2 个答案:

答案 0 :(得分:1)

  

subq $8, %rsp #the line causing the segfault

由于上面的指令没有引用内存,无法 那条指令发生了分段错误。

您可能会错误地解释您实际看到的内容。你应该

  1. 显示一个最小的示例,包含构建命令和
  2. 显示你是如何到达"导致段错误的行"结论,所以你的错误可以指出。
  3. P.S。要查找发生段错误的实际指令,请在gdb下运行程序,并在发生段错误后执行(gdb) x/i $pc命令。

答案 1 :(得分:1)

In [16]: np.subtract.outer(q, q)
Out[16]: 
array([[ 0, -4, -8],
       [ 4,  0, -4],
       [ 8,  4,  0]])

您已经编写了一个包含推送返回地址的无限循环。当你用完堆栈时,它最终会出现段错误。

在您自己的代码中为exit: # target of the CALL instruction movq $0 , %rdi call exit 标签使用其他名称。 exit可以正常工作,并且在调试时不会显示为标签。

有关GNU中本地标签的更多信息,请参阅this answer