You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编大整数斐波那契程序:超64位大整数打印实现求助

Nice work getting your big integer Fibonacci implementation running—storing the value correctly is half the battle! Printing those huge numbers is definitely a hurdle since standard printf can't handle arbitrary-precision values. Let's walk through how to implement the decimal conversion, focusing on the mod 10 and division-by-10 operations you need.

First, let's assume your big integer is stored as a little-endian byte array (common in assembly, where the lowest byte is at the start of the array), with a separate variable tracking its length in bytes. For example:

section .data
    big_num_len dd 0   ; Number of bytes in our big integer
    big_num     db 0   ; Little-endian big integer data (big_num[0] = least significant byte)

Core Idea: Decimal Conversion via Repeated Division-by-10

To convert a big integer to a decimal string, we repeatedly divide the number by 10, capture the remainder (which gives us the next digit, 0-9), and build the string in reverse. Finally, we reverse the string to get the correct order. The key challenges are implementing mod 10 and divide by 10 for arbitrary-length integers.


1. Implement bigint_mod10 (Get the Last Digit)

Calculating N mod 10 for a big integer can be done iteratively from the most significant byte (MSB) to the least (LSB). Since each byte represents a value multiplied by 256^position, we can use the property:
(a * 256 + b) mod 10 = ((a mod 10) * (256 mod 10) + b mod 10) mod 10
Since 256 mod 10 = 6, this simplifies to ((prev_remainder * 6) + current_byte) mod 10, which is fast and avoids overflow.

Here's the assembly implementation:

; Input:  eax = pointer to big_num_len, ebx = pointer to big_num
; Output: dl = big_num mod 10
bigint_mod10:
    push eax
    push ebx
    push ecx
    push edx

    xor dl, dl                  ; Initialize remainder to 0
    mov ecx, [eax]              ; Load byte length of the big integer

.mod_loop:
    ; Grab the current most significant byte (little-endian, so start at the end of the array)
    mov al, [ebx + ecx - 1]
    mov dh, dl                  ; Save previous remainder
    mov dl, al                  ; Current byte value

    ; Calculate (prev_remainder *6 + current_byte) mod10
    mov al, dh
    mov bl, 6
    mul bl                      ; ax = prev_remainder *6
    add al, dl                  ; ax = (prev*6) + current_byte
    xor ah, ah
    mov bl, 10
    div bl                      ; al = quotient, ah = new remainder
    mov dl, ah

    loop .mod_loop              ; Process next byte

    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

2. Implement bigint_div10 (Divide the Big Integer by 10)

Dividing a big integer by 10 works by processing each byte from MSB to LSB, calculating the quotient for that byte and carrying over the remainder to the next (less significant) byte. After division, we clean up any leading zeros to keep the length accurate.

; Input:  eax = pointer to big_num_len, ebx = pointer to big_num
; Output: Big integer is updated to big_num /10, big_num_len adjusted if leading zeros exist
bigint_div10:
    push eax
    push ebx
    push ecx
    push edx
    push esi

    mov ecx, [eax]              ; Byte length
    xor esi, esi                ; Initialize remainder to 0
    mov edx, ebx
    add edx, ecx
    dec edx                     ; Point to MSB (end of array)

.div_loop:
    mov al, [edx]               ; Get current MSB
    mov ah, esi                 ; Previous remainder (0-9)

    ; Calculate (ah*256 + al) /10: al = quotient, ah = new remainder
    mov bl, 10
    div bl
    mov [edx], al               ; Save quotient back to the byte
    mov esi, ah                 ; Update remainder

    dec edx
    loop .div_loop

    ; Clean up leading zeros (adjust length if MSB becomes 0)
.cleanup_zeros:
    mov ecx, [eax]
    cmp ecx, 0
    je .done
    mov edx, ebx
    add edx, ecx
    dec edx
    cmp byte [edx], 0
    jne .done
    dec dword [eax]
    jmp .cleanup_zeros

.done:
    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

3. Put It All Together: bigint_to_decimal

This function uses the above two helpers to build the decimal string, then reverses it to get the correct order. We also handle the special case where the big integer is 0 to avoid empty strings.

; Input:  eax = pointer to big_num_len, ebx = pointer to big_num, ecx = pointer to output buffer
; Output: Buffer contains null-terminated decimal string of the big integer
bigint_to_decimal:
    push eax
    push ebx
    push ecx
    push edx
    push esi
    push edi

    mov edi, ecx                ; Save buffer start address

    ; Handle special case: big integer is 0
    cmp dword [eax], 1
    jne .not_zero
    cmp byte [ebx], 0
    jne .not_zero
    mov byte [edi], '0'
    inc edi
    mov byte [edi], 0
    jmp .done

.not_zero:
    ; Build string in reverse (remainders are least significant digit first)
.build_loop:
    call bigint_mod10           ; Get next digit (dl = 0-9)
    add dl, '0'                 ; Convert to ASCII char
    mov [edi], dl
    inc edi
    call bigint_div10           ; Divide number by 10
    cmp dword [eax], 0          ; Stop when number is 0
    jne .build_loop

    ; Reverse the string to get correct order
    dec edi                     ; Point to last valid character
    mov esi, ecx                ; Point to first character
.reverse_loop:
    cmp esi, edi
    jge .reverse_done
    ; Swap characters at esi and edi
    mov al, [esi]
    mov bl, [edi]
    mov [esi], bl
    mov [edi], al
    inc esi
    dec edi
    jmp .reverse_loop

.reverse_done:
    mov byte [edi + 1], 0       ; Add null terminator

.done:
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

Usage Example

To use this in your program, you'd call bigint_to_decimal with your big integer and a buffer, then print the buffer with printf:

section .data
    big_num_len dd 16           ; Example: 16-byte big integer
    big_num     db 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
    buffer      times 256 db 0  ; Buffer for decimal string (plenty of space for large Fibs)
    format_str  db "%s", 10, 0

section .text
    global main
    extern printf

main:
    ; Assume your Fibonacci calculation has already filled big_num and big_num_len
    mov eax, big_num_len
    mov ebx, big_num
    mov ecx, buffer
    call bigint_to_decimal

    ; Print the result
    push buffer
    push format_str
    call printf
    add esp, 8

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

Key Notes

  • If your big integer uses a different storage format (e.g., big-endian, 32-bit words instead of bytes), adjust the loop directions and byte/word accesses accordingly—the core math logic stays the same.
  • For 64-bit assembly, swap 32-bit registers (eax, ebx) with 64-bit ones (rax, rbx) and adjust memory addressing as needed.
  • Make sure your buffer is large enough: Fibonacci numbers grow exponentially—for example, the 1000th Fibonacci number has 209 digits, so a 256-byte buffer is safe.

内容的提问来源于stack exchange,提问作者apilat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:04:05