尝试编写 MIPS 汇编器

问题描述 投票:0回答:1

当我使用 gcd 在线调试时,出现如下所示的未声明变量编译错误

/usr/bin/ld: /tmp/ccQ5mbJk.o: in function \`assemble':
main.c:(.text+0x2ed): undefined reference to \`parseInstruction'
/usr/bin/ld: main.c:(.text+0x316): undefined reference to \`getRegisterNumber'
/usr/bin/ld: main.c:(.text+0x338): undefined reference to \`getRegisterNumber'
/usr/bin/ld: main.c:(.text+0x364): undefined reference to \`getRegisterNumber'
/usr/bin/ld: main.c:(.text+0x463): undefined reference to \`parseDirective'

我需要帮助或建议修复下面的主要部分和空白部分。之前的所有功能都在我的源文件中定义

int main(int argc, char** argv) {
    // Checking command line arguments
    if (argc < 2) {
        printf("Usage: %s <test.asm> <test.out>\n", argv[0]);
        return -1;
    }

    // Initializing memory 
    int text_segment[MAX_SIZE];
    int data_segment[MAX_SIZE];
    memset(text_segment, 0, MAX_SIZE);
    memset(data_segment, 0, MAX_SIZE);

    // Writing to output file
    FILE* fp = fopen(argv[2], "w");
    fwrite(text_segment, 1, MAX_SIZE, fp);
    fwrite(data_segment, 1, MAX_SIZE, fp);
    fclose(fp);

    return 0;
}
// Assembling the input file
void assemble(char* filename, int* text_segment, int* data_segment) {
    int line_number = 0;
    int text_offset = 0;
    int data_offset = 0;
    char line[256];
    FILE* fp = fopen(filename, "r");

    while (fgets(line, 256, fp)) {
        // Handling blank lines
        if (strcmp(line, "\n") == 0) {
            continue;
        }

        // Parsing line 
        char* label = NULL;
        char* instruction = NULL;
        char* directive = NULL;
        char* operands = NULL;
        label = strtok(line, ":");
        instruction = strtok(NULL, " \n\t");
        directive = strtok(NULL, " \n\t");
        operands = strtok(NULL, "\n\t");

        // Handling instructions
        if (instruction) {
            // Parsing instruction
            int opcode = 0;
            int funct = 0;
            int rs = 0;
            int rt = 0;
            int rd = 0;
            int imm = 0;
            int add = 0;
            
        if (parseInstruction(instruction, &opcode, &funct)) {
            rs = getRegisterNumber(strtok(operands, ","));
            rt = getRegisterNumber(strtok(NULL, ","));
        if (opcode == 0) {
            rd = getRegisterNumber(strtok(NULL, ","));
        } else {
        imm = atoi(strtok(NULL, ","));
        }
         // Generating machine code
        int machine_code = 0;
        machine_code |= (opcode << 26);
        machine_code |= (rs << 21);
        machine_code |= (rt << 16);
        machine_code |= (rd << 11);
        machine_code |= (imm << 0);
        machine_code |= (add << 0);
        machine_code |= (funct << 0);
    // Writing machine code to text segment
        text_segment[text_offset] = machine_code;
        text_offset += 1;
        }
        // Handling directives
        if (directive) {
            // Parsing directive
            int type = 0;
            int size = 0;
            if (parseDirective(directive, &type, &size)) {
                char* token = strtok(operands, ",");
                while (token) {
                    int value = 0;
                    sscanf(token, "%d", &value);

                    // Handling .dbyte
                    if (type == 2) {
                        data_segment;
                        // Writing value to data segments
                        data_segment[data_offset] = value;
                        data_offset += 1;
                    }

                    // Handling .integer
                    if (type == 3) {
                        // Writing value to data segment
                        data_segment[data_offset] = value;
                        data_offset += 1;
                    }

                    token = strtok(NULL, ",");
                }
            }
        }
    }

    fclose(fp);
}

// Getting MIPS instruction
Instruction* getInstruction(char* instruction) {
    int i = 0;

    while (instructions[i].name) {
        if (strcmp(instructions[i].name, instruction) == 0) {
            return &instructions[i];
        }

        i++;
    }

    return NULL;
}

// Getting MIPS directive
Directive* getDirective(char* directive) {
    int i = 0;

    while (directives[i].name) {
        if (strcmp(directives[i].name, directive)) { 
            return &directives[i];
        }

        i++;
    }

    return NULL;
}

// Getting register number
int getRegisterNumber(char* regis) {
    int reg = 0;
    sscanf(regis, "$%d", &reg);
    return reg;
}


// Parsing instruction
int parseInstruction(char* instruction, int* opcode, int* funct) {
    for (int i = 0; instructions[i].name; i++) {
        if (strcmp(instruction, instructions[i].name) == 0) {
            *opcode = instructions[i].opcode;
            *funct = instructions[i].funct;
            return 1;
        }
    }
    return 0;
}

// Parsing directive
int parseDirective(char* directive, int* type, int* size) {
    Directive* dir = getDirective(directive);
    if (dir) {
        *type = dir->n;
        *size = dir->size;
        return 1;
    } else {
        return 0;
    }
}
}
c assembly mips
1个回答
0
投票

以最高评论为序...

请注意,您的代码(已发布)将无法编译,因为您在

}
中缺少结束符
assemble
。这可能会导致您的一些问题。此外,您在定义之前调用
parseInstruction
。我会使用前向函数声明或重新排序函数。 – 克雷格·埃斯蒂

我将如何宣布?我在这个项目上花费了无数时间—— 安德鲁·谢尔布

还有 assemble } 支架一直在底部,除非我贴错了,或者它不应该在那里?我写了整个汇编来包括它后面的所有东西—— 安德鲁·谢尔布

是的,你有正确数量的

}
但最后的
}
在错误的位置,所以编译器认为你有词法“嵌套”函数(标准 C 中不存在)。 – 克雷格·埃斯蒂


好吧,我已经重构了代码,所以它可以干净地编译。它仍然有一个关于设置

label
使用它的警告。

我不得不综合你的一些missing

struct
定义让它干净地编译。

但是,这解决了您关于缺失功能的原始问题。

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

// synthesized missing definitions ...
#if 1
#define MAX_SIZE    1024

typedef struct {
    char *name;
    int n;
    int size;
} Directive;

Directive directives[1000];

typedef struct {
    char *name;
    int opcode;
    int funct;
} Instruction;

Instruction instructions[1000];

#endif

// forward function declarations
#if 1
void assemble(char *filename, int *text_segment, int *data_segment);
Instruction *getInstruction(char *instruction);
Directive *getDirective(char *directive);
int getRegisterNumber(char *regis);
int parseInstruction(char *instruction, int *opcode, int *funct);
int parseDirective(char *directive, int *type, int *size);
#endif

int
main(int argc, char **argv)
{
    // Checking command line arguments
    if (argc < 2) {
        printf("Usage: %s <test.asm> <test.out>\n", argv[0]);
        return -1;
    }

    // Initializing memory
    int text_segment[MAX_SIZE];
    int data_segment[MAX_SIZE];

// NOTE/BUG: compiler warns about third arg being too small
#if 0
    memset(text_segment, 0, MAX_SIZE);
    memset(data_segment, 0, MAX_SIZE);
#else
    memset(text_segment, 0, sizeof(text_segment));
    memset(data_segment, 0, sizeof(data_segment));
#endif

    // Writing to output file
    FILE *fp = fopen(argv[2], "w");

    fwrite(text_segment, 1, MAX_SIZE, fp);
    fwrite(data_segment, 1, MAX_SIZE, fp);
    fclose(fp);

    return 0;
}

// Assembling the input file
void
assemble(char *filename, int *text_segment, int *data_segment)
{
// NOTE/BUG: line_number not used
#if 0
    int line_number = 0;
#endif
    int text_offset = 0;
    int data_offset = 0;
    char line[256];
    FILE *fp = fopen(filename, "r");

    while (fgets(line, 256, fp)) {
        // Handling blank lines
        if (strcmp(line, "\n") == 0) {
            continue;
        }

        // Parsing line
// NOTE/BUG: compiler warning: label set but not used
        char *label = NULL;
        char *instruction = NULL;
        char *directive = NULL;
        char *operands = NULL;

        label = strtok(line, ":");
        instruction = strtok(NULL, " \n\t");
        directive = strtok(NULL, " \n\t");
        operands = strtok(NULL, "\n\t");

        // Handling instructions
        if (instruction) {
            // Parsing instruction
            int opcode = 0;
            int funct = 0;
            int rs = 0;
            int rt = 0;
            int rd = 0;
            int imm = 0;
            int add = 0;

            if (parseInstruction(instruction, &opcode, &funct)) {
                rs = getRegisterNumber(strtok(operands, ","));
                rt = getRegisterNumber(strtok(NULL, ","));
                if (opcode == 0) {
                    rd = getRegisterNumber(strtok(NULL, ","));
                }
                else {
                    imm = atoi(strtok(NULL, ","));
                }
                // Generating machine code
                int machine_code = 0;

                machine_code |= (opcode << 26);
                machine_code |= (rs << 21);
                machine_code |= (rt << 16);
                machine_code |= (rd << 11);
                machine_code |= (imm << 0);
                machine_code |= (add << 0);
                machine_code |= (funct << 0);
                // Writing machine code to text segment
                text_segment[text_offset] = machine_code;
                text_offset += 1;
            }
            // Handling directives
            if (directive) {
                // Parsing directive
                int type = 0;
                int size = 0;

                if (parseDirective(directive, &type, &size)) {
                    char *token = strtok(operands, ",");

                    while (token) {
                        int value = 0;

                        sscanf(token, "%d", &value);

                        // Handling .dbyte
                        if (type == 2) {
// NOTE/BUG: statement with no effect
#if 0
                            data_segment;
#endif
                            // Writing value to data segments
                            data_segment[data_offset] = value;
                            data_offset += 1;
                        }

                        // Handling .integer
                        if (type == 3) {
                            // Writing value to data segment
                            data_segment[data_offset] = value;
                            data_offset += 1;
                        }

                        token = strtok(NULL, ",");
                    }
                }
            }
        }

        fclose(fp);
    }
}

// Getting MIPS instruction
Instruction *
getInstruction(char *instruction)
{
    int i = 0;

    while (instructions[i].name) {
        if (strcmp(instructions[i].name, instruction) == 0) {
            return &instructions[i];
        }

        i++;
    }

    return NULL;
}

// Getting MIPS directive
Directive *
getDirective(char *directive)
{
    int i = 0;

    while (directives[i].name) {
        if (strcmp(directives[i].name, directive)) {
            return &directives[i];
        }

        i++;
    }

    return NULL;
}

// Getting register number
int
getRegisterNumber(char *regis)
{
    int reg = 0;

    sscanf(regis, "$%d", &reg);
    return reg;
}

// Parsing instruction
int
parseInstruction(char *instruction, int *opcode, int *funct)
{
    for (int i = 0; instructions[i].name; i++) {
        if (strcmp(instruction, instructions[i].name) == 0) {
            *opcode = instructions[i].opcode;
            *funct = instructions[i].funct;
            return 1;
        }
    }
    return 0;
}

// Parsing directive
int
parseDirective(char *directive, int *type, int *size)
{
    Directive *dir = getDirective(directive);

    if (dir) {
        *type = dir->n;
        *size = dir->size;
        return 1;
    }
    else {
        return 0;
    }
}

在上面的代码中,我使用了

cpp
条件来表示旧代码与新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:这可以通过运行文件来清理

unifdef -k

© www.soinside.com 2019 - 2024. All rights reserved.