Я новичок в языке ассемблера. Как разорвать цикл рекурсии?

Я новичок в языке ассемблера. Я создаю функцию простой факторизации в синтаксисе 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, %rdi
    xor %rax, %rax
    call printf
    ret

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

Когда я пытаюсь напечатать простое число факторизации, он говорит

2 2 2 2 2 2 2 2 ...

Мне жаль. Я очень новичок. Можете ли вы объяснить, почему это печатает только 2 бесконечно? Что мне нужно сделать, чтобы напечатать простую факторизацию?


person Soomin Im    schedule 05.11.2020    source источник
comment
Почему у вас есть все эти переходы с нулевым смещением (переход к метке, которая является ближайшей следующей инструкцией)?   -  person 1201ProgramAlarm    schedule 05.11.2020


Ответы (1)


Вызывающий fact_print предполагает, что регистр eax не будет изменен, но это не так. Когда fact_print вернется, eax будет иметь значение, возвращенное printf (количество выведенных символов).

Вы захотите сохранить eax где-нибудь (в неизмененном регистре или в стеке) перед вызовом fact_print, а затем восстановить его по возвращении.

person 1201ProgramAlarm    schedule 05.11.2020
comment
... или используйте любой из нескольких регистров с сохранением вызовов в соглашениях о вызовах x86-64 вместо стека. Какие регистры сохраняются при вызове функции linux x86-64 - person Peter Cordes; 06.11.2020