我正在进行一项任务,我已经为给定的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
,算术异常。