Brainfuck примеры реализаций

Март 26, 2024, 12:03 - Время чтения: 3 минуты

Python

def brainfuck_interpreter(code):
    tape = [0] * 30000
    pointer = 0
    output = ""

    brackets = find_brackets(code)

    code_ptr = 0
    while code_ptr < len(code):
        instruction = code[code_ptr]

        if instruction == ">":
            pointer += 1
        elif instruction == "<":
            pointer -= 1
        elif instruction == "+":
            tape[pointer] += 1
        elif instruction == "-":
            tape[pointer] -= 1
        elif instruction == ".":
            output += chr(tape[pointer])
        elif instruction == ",":
            tape[pointer] = ord(input()[:1])
        elif instruction == "[" and tape[pointer] == 0:
            code_ptr = brackets[code_ptr]
        elif instruction == "]" and tape[pointer] != 0:
            code_ptr = brackets[code_ptr]

        code_ptr += 1

    return output

def find_brackets(code):
    brackets = {}
    stack = []

    for i, char in enumerate(code):
        if char == "[":
            stack.append(i)
        elif char == "]":
            open_bracket = stack.pop()
            brackets[open_bracket] = i
            brackets[i] = open_bracket

    return brackets

bf_code = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++."
output = brainfuck_interpreter(bf_code)
print(output)

C

#include <stdio.h>

#define MEMORY_SIZE 30000

void brainfuck_interpreter(char *code) {
    char memory[MEMORY_SIZE] = {0};
    char* ptr = memory;

    while (*code != '\0') {
        switch (*code) {
            case '>':
                ++ptr;
                break;
            case '<':
                --ptr;
                break;
            case '+':
                ++(*ptr);
                break;
            case '-':
                --(*ptr);
                break;
            case '.':
                putchar(*ptr);
                break;
            case ',':
                *ptr = getchar();
                break;
            case '[':
                if (*ptr == 0) {
                    int loop_count = 1;
                    while (loop_count > 0) {
                        ++code;
                        if (*code == '[') {
                            ++loop_count;
                        } else if (*code == ']') {
                            --loop_count;
                        }
                    }
                }
                break;
            case ']':
                if (*ptr != 0) {
                    int loop_count = 1;
                    while (loop_count > 0) {
                        --code;
                        if (*code == ']') {
                            ++loop_count;
                        } else if (*code == '[') {
                            --loop_count;
                        }
                    }
                }
                break;
        }

        ++code;
    }
}

int main() {
    char bf_code[] = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++.";

    brainfuck_interpreter(bf_code);

    return 0;
}

C++

#include <iostream>

#define MEMORY_SIZE 30000

void brainfuck_interpreter(char* code) {
    char memory[MEMORY_SIZE] = { 0 };
    char* ptr = memory;

    while (*code != '\0') {
        switch (*code) {
        case '>':
            ++ptr;
            break;
        case '<':
            --ptr;
            break;
        case '+':
            ++(*ptr);
            break;
        case '-':
            --(*ptr);
            break;
        case '.':
            std::cout << *ptr;
            break;
        case ',':
            std::cin >> *ptr;
            break;
        case '[':
            if (*ptr == 0) {
                int loop_count = 1;
                while (loop_count > 0) {
                    ++code;
                    if (*code == '[') {
                        ++loop_count;
                    }
                    else if (*code == ']') {
                        --loop_count;
                    }
                }
            }
            break;
        case ']':
            if (*ptr != 0) {
                int loop_count = 1;
                while (loop_count > 0) {
                    --code;
                    if (*code == ']') {
                        ++loop_count;
                    }
                    else if (*code == '[') {
                        --loop_count;
                    }
                }
            }
            break;
        }

        ++code;
    }
}

int main() {
    char bf_code[] = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++.";

    brainfuck_interpreter(bf_code);

    return 0;
}

x86 IO порты

Май 13, 2023, 19:05 - Время чтения: ~1 минут

IO порты представляют собой входы/выходы (Input/Output) и используются для обмена информацией между микроконтроллерами и внешними устройствами. В данной статье мы рассмотрим работу с IO портами на платформе x86.

На платформе x86 IO порты адресуются 16-битным номером (0x0000 – 0xFFFF). Для работы с IO портами в ОС Linux используется файловая система /dev/port. В Windows доступ к портам осуществляется через функции WinAPI: ReadPort, WritePort.

Для чтения данных из порта на x86 микропроцессоре существует три команды: inb, inw, inl. Каждый из этих операторов читает данные определенного размера (один байт, два байта, четыре байта) из заданного порта в указанный регистр.

Для записи данных в порт на x86 микропроцессоре существует три команды: outb, outw, outl. Каждый из этих операторов записывает данные определенного размера (один байт, два байта, четыре байта) из указанного регистра в заданный порт.

Для упрощения работы с IO портами на x86 микропроцессорах, можно использовать специальные функции, объявленные в заголовочном файле asm/io.h.

Примеры функций для работы с IO портами на x86:

/**
 * @brief Получение одного байта из порта
 *
 * @param port Порт
 * @return uint8_t Значение из порта
 */
uint8_t hal_ioport_inb(uint16_t port) {
    uint8_t ret;
    asm volatile("inb %1, %0"
                 : "=a"(ret)
                 : "Nd"(port));
    return ret;
}

/**
 * @brief Получение 2 байт(word) из порта
 *
 * @param port Порт
 * @return uint16_t Значение из порта
 */
uint16_t hal_ioport_inw(uint16_t port) {
    uint16_t ret;
    asm volatile("inw %1, %0"
                 : "=a"(ret)
                 : "Nd"(port));
    return ret;
}

/**
 * @brief Получение 4 байт из порта
 *
 * @param port Порт
 * @return uint32_t Значение из порта
 */
uint32_t hal_ioport_inl(uint16_t port) {
    uint32_t ret;
    asm volatile("inl %1, %0"
                 : "=a"(ret)
                 : "Nd"(port));
    return ret;
}

/**
 * @brief Ввод одного байта в порт
 *
 * @param port Порт
 * @param val Входные данные
 */
void hal_ioport_outb(uint16_t port, uint8_t val) {
    asm volatile("outb %0, %1"
                 :
                 : "a"(val), "Nd"(port));
}

/**
 * @brief Ввод 2 байт (word) в порт
 *
 * @param port Порт
 * @param val Входные данные
 */
void hal_ioport_outw(uint16_t port, uint16_t val) {
    asm volatile("outw %0, %1"
                 :
                 : "a"(val), "Nd"(port));
}

/**
 * @brief Ввод 4 байт в порт
 *
 * @param port Порт
 * @param val  Входные данные
 */
void hal_ioport_outl(uint16_t port, uint32_t val) {
    asm volatile("outl %0, %1"
                 :
                 : "a"(val), "Nd"(port));
}