ฉันยังใหม่กับภาษาแอสเซมบลี ฉันจะทำลายลูปการเรียกซ้ำได้อย่างไร [ทำซ้ำ]

ฉันยังใหม่กับภาษาแอสเซมบลี ฉันกำลังสร้างฟังก์ชันการแยกตัวประกอบเฉพาะในไวยากรณ์ 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