我是汇编语言的新手如何中断递归循环?

问题描述

我是汇编语言的新手。我正在用AT&T x64 / GNU语法创建素数分解函数

这是..


.data
.text
.global main
.prime_end: .string "End\n"
.fact_end: .string "Finish\n"
.fact_print: .string "%d\n"

prime: 
mov %rsi,%rax
    mov $0,%rdi
    cmp $2,%rax
    jl prime_end

    jmp prime_base

prime_base:    # r10 = 1
    mov $1,%r10
    jmp prime_start

prime_start:    # r10 + 1 = 2
    inc %r10
    jmp prime_check

prime_check:
    cqto
    div %r10    # rsi = 10,rax = 10,rax / r10 = 10/2 

    cmp $0,%rdx    # rdx = 0,rax = 5
    jne prime_start

    jmp fact_check

fact_check:    # rsi = 10,rax = 10
    mov %rsi,%rax
    cqto
    div %r10    # 10 / 2 

    jmp prime_fact

prime_fact:
    cmp %r10,%rax    # to end function
    jl fact_end

    call fact_print     # where I think it should be printed

    mov %rax,%rsi    # rax = 5,rsi = 5
    add %rdx,%rsi    # rdx = 0,rsi = 5

    cmp $1,%rsi    # if 5 = 1,end function
    jne prime_base    

    jmp fact_end

fact_print:
    mov $.fact_print,%rdi
    mov %r10,%rsi
    xor %rax,%rax
    call printf
    ret

fact_end:
    mov $.fact_end,%rdi
    xor %rax,%rax
    call printf
    ret

prime_end:
    mov $.prime_end,%rax
    call printf
    ret

main:
    mov $10,%rsi    # check 10 ... expect 2 5
    call prime

当我尝试打印素数分解数时,它说

2 2 2 2 2 2 2 2 ...

对不起。我很新。您能解释一下为什么只打印两次吗?要打印素因数分解,我该怎么办?

解决方法

fact_print的调用者假定eax寄存器不会被更改,但事实并非如此。返回fact_print时,eax将具有printf返回的值(输出的字符数)。

您将需要在调用eax之前将fact_print存储在某个地方(未修改的寄存器中,或放在堆栈中),然后在返回时将其恢复。