Saya baru mengenal bahasa assembly. Bagaimana cara memutus loop rekursi? [duplikat]

Saya baru mengenal bahasa assembly. Saya membuat fungsi faktorisasi prima dalam sintaks AT&T x64/GNU.

Di sini adalah..


.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, %rdi
    xor %rax, %rax
    call printf
    ret

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

Saat saya mencoba mencetak bilangan faktorisasi prima, tertulis

2 2 2 2 2 2 2 2 ...

Saya minta maaf. Saya sangat baru. Bisakah Anda menjelaskan mengapa ini hanya mencetak 2 tanpa batas? Apa yang harus saya lakukan untuk mencetak faktorisasi prima?


person Soomin Im    schedule 05.11.2020    source sumber
comment
Mengapa Anda memiliki semua lompatan offset nol (melompat ke label yang merupakan instruksi selanjutnya)?   -  person 1201ProgramAlarm    schedule 05.11.2020


Jawaban (1)


Penelepon fact_print berasumsi bahwa register eax tidak akan diubah, namun hal ini tidak terjadi. Ketika fact_print kembali, eax akan memiliki nilai yang dikembalikan sebesar printf (jumlah karakter yang dihasilkan).

Anda ingin menyimpan eax di suatu tempat (dalam register yang tidak diubah, atau di tumpukan) sebelum memanggil fact_print, lalu memulihkannya saat kembali.

person 1201ProgramAlarm    schedule 05.11.2020
comment
... atau gunakan salah satu dari beberapa register panggilan yang dipertahankan dalam konvensi panggilan x86-64, alih-alih tumpukan. Register apa yang dipertahankan melalui panggilan fungsi linux x86-64 - person Peter Cordes; 06.11.2020