调用printf后的程序集控制流程

时间:2017-03-23 11:54:14

标签: assembly x86-64 control-flow

我正在进行一项任务,我已经为给定的C程序编写了等效的汇编代码,该程序可以找到数字的素数因子。
在使用gdb进行调试时,我注意到执行语句的顺序有一些奇怪的行为。第一次调用printf后,它会跳回到L1中的divq %r8,我真的不明白为什么。没有跳转语句,除法导致浮点异常,导致程序崩溃。有什么想法发生了什么?现在不要介意明显的逻辑错误:)

这是我的源代码:

    .file "factor.s"
    .section    .rodata
    strout: .string "%ld %s\n"
    STR0: .string "is a prime factor"

    .text
    .globl factor
    .section .text

factor:
        pushq   %rbp            # setup stack frame
        movq    %rsp, %rbp      # setup stack frame
        movq    %rdi, %r8       # save first param(n) in r8
        shrq    $1, %r8      # bitshift r8 by 1 (div by 2)
                                # int64_t f = n/2 complete
                                # f is in r8
        movq    %rdi, %rax      # save first param in rax
        movq    %rdi, %r9       # save first param in r9
L0:
        cmpq    $1, %r8         # while (f > 1)
        jbe     L1              # if f is not greater than 1
        cqto                    # convert %rax to %rdx:%rax

        idivq   %r8             # It hops back here somewhy
        cmpq    $0, %rdx        
        je      L1              # break (jump if %rax equals 0)
        decq    %r8             # f--
        jmp     L0              # if f still is greater than one
                                # jump to L0

    L1:                         # outside while loop
        cmpq    $1, %r8         # compare f and 1
        je      L2              # if f == 1, jump
        movq    %r9, %rax
        cqto                    # convert %rax to %rdx:%rax
        divq    %r8             # n%f
        movq    %rdx, %rdi      # push param
        call    factor          # factor (n/f)
        movq    %r8, %rdi       # push param
        call    factor          # factor(f)
        jmp     L3              # skip else block

    L2:
        movq    %r8, %rsi       # push params, fixed pushing rax to r8
        movq    $strout, %rdi   # push params
        movq    $STR0, %rdx     # push params
        call printf             # printf
    L3:
        leave                   # cleanup stackframe
        ret                     # and return


        .globl  main
    main:
        pushq   %rbp
        movq    %rsp, %rbp
        movq    $11, %rdi   # 11 for easier testing
        call    factor
        movq    $0, %rax
        ret

这是我的调试日志(gdb) 信息寄存器是:

    rax            0x2  2
    rbx            0x0  0
    rcx            0x0  0
    rdx            0x2  2
    rsi            0x2  2
    rdi            0x2  2
    rbp            0x7fffffffdfd0   0x7fffffffdfd0
    rsp            0x7fffffffdfd0   0x7fffffffdfd0
    r8             0x1  1
    r9             0x2  2
    r10            0x4  4
    r11            0x1  1
    r12            0x400400 4195328
    r13            0x7fffffffe0d0   140737488347344
    r14            0x0  0
    r15            0x0  0
    rip            0x40053f 0x40053f <L2+3>
    eflags         0x246    [ PF ZF IF ]
    cs             0x33 51
    ss             0x2b 43
    ds             0x0  0
    es             0x0  0
    fs             0x0  0
    gs             0x0  0
    (gdb) s
    48  movq    $STR0, %rdx     # push params
    (gdb) 
    49  call printf             # printf
    (gdb) s
    2 is a prime factor

错误消息是:

  

编程接收信号SIGFPE,算术异常。
  L1()at factor.s:38
  38 divq%r8#n%f
  (gdb)s

程序终止,信号SIGFPE,算术异常。

0 个答案:

没有答案