Как отделить / декодировать двоичную строку из входного файла? (С) - PullRequest
0 голосов
/ 30 апреля 2018

Моей программе удается читать построчно во входном текстовом файле, и теперь я пытаюсь обработать определенный раздел. Вход выглядит так:

^Other stuff^
CODE
10001100001000100000000000000000
00000000010000110010000000100000
10101100001001000000000000000000
(End of file after CODE section)

Двоичные числа - это инструкция MIPS, и может быть любое количество строк (в качестве примера я использовал 3). Мне нужно разделить каждую 32-битную строку на 6 секций: OpCode, rs, rt, rd, shamt, funct (6, 5, 5, 5, 5, 6 бит соответственно).

Что я уже сделал: моя программа уже может прочитать введенный текст и вызвать соответствующую функцию для каждого раздела. Вот небольшой фрагмент для контекста:

char line[64];

int mode = 0; //for parsing sections, 1 = REGISTER, 2 = MEMORY, 3 = CODE

while (fgets(line, sizeof line, filePtr) != NULL) {
    if (strcmp(line, "REGISTERS\n") == 0) {
        mode = 1;
    }

    else if (strcmp(line, "MEMORY\n") == 0) {
        mode = 2;
    }

    else if (strcmp(line, "CODE\n") == 0) {
        mode = 3;
    }

    switch (mode) {
    case 1:
        parseRegisters(line, registers); //this part works
        break;
    case 2:
        parseMemory(line, memory);  //this part works
        break;
    case 3:
        parseCode(line);  //have not started writing this function
        break;
    default:
        break;
    }

Так что в этом разделе он начинает вызывать parseCode () для каждой двоичной строки. Как мне написать parseCode (), чтобы разделить каждую строку на 6 разделов? Затем мне нужно выполнить различные действия в зависимости от того, к чему декодируются разделы, но я уже рассмотрел это.

1 Ответ

0 голосов
/ 01 мая 2018

Строка нулей (0) и единиц (1) может быть преобразована в 32-разрядное число с помощью strtoul:

char *end;
uint32_t value = strtoul(line, &end, 2);

Вы можете использовать end, чтобы убедиться, что весь line был правильно использован. Третий аргумент указывает базу, используемую для преобразования.

Получив значение, вы можете легко замаскировать соответствующие части числа с помощью обычной логики маскирования битов. Место, где эти биты на самом деле находятся, зависит от платформы, но предполагается, что они имеют порядковый номер:

#define OPCODE_MASK (0x3FUL <<  0)
#define RS_MASK     (0x1FUL <<  6)
#define RT_MASK     (0x1FUL << 11)
#define RD_MASK     (0x1FUL << 16)
#define SHAMT_MASK  (0x1FUL << 21)
#define FUNCT_MASK  (0x3FUL << 26)

#define GET_OPCODE(X) (((X) & OPCODE_MASK) >>  0)
#define GET_RS(X)     (((X) & RS_MASK)     >>  6)
#define GET_RT(X)     (((X) & RT_MASK)     >> 11)
#define GET_RD(X)     (((X) & RD_MASK)     >> 16)
#define GET_SHAMT(X)  (((X) & SHAMT_MASK)  >> 21)
#define GET_FUNCT(X)  (((X) & FUNCT_MASK)  >> 26)

В качестве альтернативы, если вы не возражаете против поведения платформы, вы можете попытаться распаковать значение через структуру с битовыми полями.

union decode {
    uint32_t code;
    struct {
        uint32_t opcode : 6;
        uint32_t rs     : 5;
        uint32_t rt     : 5;
        uint32_t rd     : 5;
        uint32_t shamt  : 5;
        uint32_t funct  : 6;
    };
};

DEMO

...