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;
}
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));
}