subq$8%rsp分段错误



我正在学习在Linux(gcc(上使用x86-64汇编(AT&T(进行编码,但在这段琐碎的代码中找不到解决分段错误的方法。我看到了一些关于堆栈对齐的问题;然而,即使我尝试8美元或16美元,这也会失败:

.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

在调用printf之后,我编写的其他程序似乎运行良好。上面的代码出了什么问题?无论是否调用退出,代码都会失败。此操作和下面的代码正在失败。我使用编译

gcc -o test test.s

整个代码:

.text
formatStr: .asciz "%ld"
resultStr: .asciz "The result is: %dn"
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

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

0x4004e5 <exit+7>:  callq  0x4004de <exit>
exit:                   # target of the CALL instruction
    movq    $0 , %rdi
    call    exit

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

在您自己的代码中为exit标签使用不同的名称。.Lexit可以工作,并且在调试时不会显示为标签。

有关GNU中的本地标签语法的更多信息,请参阅此答案。

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

由于上面的指令没有引用内存,不可能在该指令上发生分段故障。

你可能误解了你实际看到的东西。你应该

  1. 显示一个最小的示例,包括构建命令,以及
  2. 展示你是如何得出"导致segfault的那条线"的结论的,这样你的错误就可以被指出

p.S.要找到发生segfault的实际指令,请在gdb下运行程序,并在实际发生segfort后执行(gdb) x/i $pc命令。

最新更新