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

C与汇编实现大数计算器:如何存储标准输入后缀表达式以便汇编计算?

Hey there! Let's tackle this problem step by step since you're building an arbitrary-precision calculator combining C and assembly. The key here is to pick a storage format that's easy to parse from stdin in C and straightforward to manipulate in assembly, especially for postfix expression inputs.

1. Decimal Digit Array (Simplest for Basic Operations)

This is the most intuitive format for handling decimal input, perfect for addition/subtraction (and even multiplication if you're doing digit-by-digit operations).

We'll store each digit of the large number as a single unsigned char (0-9), and wrap it in a struct to track the length and sign:

typedef struct {
    unsigned char *digits;  // Stores digits in reverse order (lowest digit first!)
    size_t length;          // Number of digits
    int is_negative;        // 1 for negative, 0 for positive
} BigNumber;
  • Reverse order reasoning: When doing arithmetic in assembly, you'll want to start from the least significant digit (rightmost of the original number). Storing digits reversed means you can loop from index 0 upwards without calculating offsets from the end of the array. For example, the number "1234" becomes [4,3,2,1] in the array.
  • Dynamic allocation: Since numbers can be any length, we use malloc() to allocate exactly the space needed for each number.

2. Binary Block Array (Faster for Complex Operations)

If you plan to implement multiplication/division or more advanced operations, converting the decimal input into binary blocks (e.g., 64-bit unsigned integers) will make assembly operations much faster. This lets you use native register-sized operations instead of digit-by-digit processing.

Here's a struct for this format:

#include <stdint.h>

typedef struct {
    uint64_t *blocks;       // Stores number as 64-bit binary chunks (LSB first)
    size_t block_count;     // Number of 64-bit blocks
    int is_negative;        // Sign flag
} BigNumberBinary;
  • Tradeoff: Parsing decimal strings into binary blocks requires more C code (you'll need to implement decimal-to-binary multi-word conversion), but assembly operations will be far more efficient.
Input Handling in C

First, you need to read and split the postfix expression into operands and operators. Here's a simplified example of parsing a decimal operand into our BigNumber struct:

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

BigNumber parse_bignum(const char *str) {
    BigNumber num = {0};
    size_t str_len = strlen(str);
    size_t start_idx = 0;

    // Handle negative signs
    if (str[0] == '-') {
        num.is_negative = 1;
        start_idx = 1;
    }

    num.length = str_len - start_idx;
    // Allocate memory for reversed digits
    num.digits = malloc(num.length);
    if (!num.digits) {
        // Handle allocation failure (set length to 0 as error flag)
        num.length = 0;
        return num;
    }

    // Fill digits in reverse order
    for (size_t i = 0; i < num.length; i++) {
        char c = str[start_idx + num.length - 1 - i];
        if (!isdigit(c)) {
            // Invalid character - clean up and return error
            free(num.digits);
            num.digits = NULL;
            num.length = 0;
            return num;
        }
        num.digits[i] = c - '0'; // Convert char to numeric value
    }

    // Edge case: handle all-zero inputs (e.g., "0000" becomes length 1, digit 0)
    if (num.length > 1) {
        size_t first_non_zero = num.length;
        for (size_t i = num.length - 1; i < num.length; i--) {
            if (num.digits[i] != 0) {
                first_non_zero = i;
                break;
            }
        }
        if (first_non_zero != num.length) {
            num.length = first_non_zero + 1;
            num.digits = realloc(num.digits, num.length);
        }
    }

    return num;
}

To split the input line into tokens (operands/operators), you can use strtok() with spaces as delimiters, or manually iterate through the input string.

Interfacing with Assembly

Once you have your BigNumber structs, passing them to assembly is straightforward thanks to C's function calling conventions.

For example, in x86-64 System V (common on Linux/macOS), you'd declare an assembly function prototype in C like this:

extern BigNumber big_add(BigNumber a, BigNumber b);

In assembly, you can access the struct members via their memory offsets. For our BigNumber struct:

  • digits is at offset 0 (8 bytes for the pointer)
  • length is at offset 8 (8 bytes for size_t)
  • is_negative is at offset 16 (4 bytes for int, padded to 8 bytes for alignment)

Your assembly function would receive pointers to the BigNumber structs in registers (or on the stack, depending on the calling convention), then access the digits array and length to perform the addition.

Pro Tips
  • Memory management: Always free() the digits or blocks pointers when you're done with a BigNumber to avoid memory leaks.
  • Error handling: Add checks for invalid input (non-digit characters, empty operands) in your C parsing code to avoid crashes in assembly.
  • Start simple: Implement addition first with the decimal digit array format, then move to more complex operations or the binary block format once you have the basics working.
  • Debugging: Use C to print out the contents of your BigNumber structs before passing them to assembly—this helps verify your parsing logic is correct.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:40:20