Задать вопрос
Ответы пользователя по тегу C++
  • Как в этом коде перенести загрузчик в виртуальный машинный код?

    axifive
    @axifive
    Software Engineer
    Да просто перенести runLoader() в класс, и добавить его вызов в конструкторе.

    spoiler
    class CPU {
    private:
        static constexpr size_t MEMORY_SIZE = 65536;
        std::array<std::bitset<256>, 4> registers;
        uint16_t ip = 0;
        uint16_t program_base = 0;
        std::vector<uint16_t> memory;
        uint64_t sleep_cycles = 0;
        uint64_t clock_freq;
        std::chrono::time_point<std::chrono::high_resolution_clock> last_tick;
        std::string bitsToDec(const std::bitset<256>& bits) {
            std::string dec = "0";
            for (int i = 255; i >= 0; --i) {
                int carry = 0;
                for (int j = dec.size() - 1; j >= 0; --j) {
                    int digit = (dec[j] - '0') * 2 + carry;
                    carry = digit / 10;
                    dec[j] = (digit % 10) + '0';
                }
                if (carry > 0)
                    dec.insert(dec.begin(), carry + '0');
                if (bits[i]) {
                    carry = 1;
                    for (int j = dec.size() - 1; j >= 0; --j) {
                        int digit = (dec[j] - '0') + carry;
                        carry = digit / 10;
                        dec[j] = (digit % 10) + '0';
                        if (carry == 0)
                            break;
                    }
                    if (carry > 0)
                        dec.insert(dec.begin(), carry + '0');
                }
            }
            return dec.empty() ? "0" : dec;
        }
        void runLoader() {
            printf("Добро пожаловать в эмулятор ОС\n\n");
            printf("Доступные команды:\n");
            printf("  run <машинный код>  - загрузить и выполнить программу. Машинный код задаётся шестнадцатеричными числами через пробел.\n");
            printf("  help                - вывести справку по командам.\n");
            printf("  programs            - показать доступные для запуска программы\n");
            printf("  exit                - завершить работу ОС.\n\n");
            const uint16_t PROGRAM_LOAD_ADDRESS = USER_PROGRAM_BASE;
            while (true) {
                printf("OS> ");
                std::string line;
                std::getline(std::cin, line);
                if (line.empty())
                    std::getline(std::cin, line);
                std::istringstream iss(line);
                std::string command;
                iss >> command;
                if (command == "exit") {
                    printf("Завершение работы ОС.\n");
                    break;
                }
                else if (command == "help") {
                    printf("\nДоступные команды:\n");
                    printf("  run <машинный код> - загрузить и выполнить программу. Пример:\n");
                    printf("    run 0x1001 0x1401 0x3000 ... 0x9000\n");
                    printf("  programs - показать доступные для запуска программы\n");
                    printf("  exit                - выйти из ОС.\n\n");
                }
                else if (command == "run") {
                    std::vector<uint16_t> program;
                    std::string token;
                    while (iss >> token) {
                        try {
                            if (token.find("0x") == 0 || token.find("0X") == 0)
                                token = token.substr(2);
                            uint16_t instr = static_cast<uint16_t>(std::stoul(token, nullptr, 16));
                            program.push_back(instr);
                        }
                        catch (std::exception& e) {
                            fprintf(stderr, "Ошибка преобразования токена '%s': %s\n", token.c_str(), e.what());
                        }
                    }
                    if (program.empty()) {
                        fprintf(stderr, "Не указан машинный код для загрузки.\n");
                        continue;
                    }
                    try {
                        load_program(PROGRAM_LOAD_ADDRESS, program);
                        start_program(PROGRAM_LOAD_ADDRESS);
                        printf("Запуск программы...\n");
                        execute();
                        printf("\nПрограмма завершила работу.\n");
                    }
                    catch (std::exception& e) {
                        fprintf(stderr, "Ошибка при загрузке/исполнении программы: %s\n", e.what());
                    }
                }
                else if (command == "programs") {
                    printf("\nДоступные программы (Вы можете скопировать их и вставить в команду run):\n");
                    printf("\nВычисление чисел Фибоначчи: 0x1001 0x1401 0x3000 0x63E8 0x3400 0x63E8 0x2840 0x3800 0x63E8 0x4100 0x4600 0x5006\n");
                }
                else {
                    fprintf(stderr, "Неизвестная команда. Введите 'help' для справки.\n");
                }
            }
        }
        uint8_t getDestReg(uint16_t instr) { return (instr >> 10) & 0x03; }
        uint8_t getSrcReg1(uint16_t instr) { return (instr >> 8) & 0x03; }
        uint8_t getSrcReg2(uint16_t instr) { return (instr >> 6) & 0x03; }
        uint8_t getImmediateValue(uint16_t instr) { return instr & 0xFF; }
        uint16_t getJumpOffset(uint16_t instr) { return instr & 0x0FFF; }
        void syncClock() {
            auto now = std::chrono::high_resolution_clock::now();
            std::chrono::nanoseconds target_duration(1000000000 / clock_freq);
            auto elapsed = now - last_tick;
            if (elapsed < target_duration) {
                while (std::chrono::high_resolution_clock::now() - last_tick < target_duration) {}
            }
            last_tick = std::chrono::high_resolution_clock::now();
        }
    public:
        CPU(uint64_t freq) : clock_freq(freq), memory(MEMORY_SIZE, 0) {
            last_tick = std::chrono::high_resolution_clock::now();
            runLoader();
        }
        void load_program(uint16_t address, const std::vector<uint16_t>& program) {
            if (address + program.size() >= MEMORY_SIZE) {
                throw std::out_of_range("Программа требует слишком много памяти");
            }
            std::copy(program.begin(), program.end(), memory.begin() + address);
        }
        void start_program(uint16_t entry_point) {
            ip = entry_point;
            program_base = entry_point;
            registers.fill(std::bitset<256>(0));
            sleep_cycles = 0;
        }
        void execute() {
            while (ip < MEMORY_SIZE) {
                syncClock();
                if (sleep_cycles > 0) {
                    sleep_cycles--;
                    continue;
                }
                uint16_t instr = memory[ip++];
                uint8_t opcode = (instr >> 12) & 0x0F;
                switch (opcode) {
                case MOV_IMM: {
                    uint8_t reg = getDestReg(instr);
                    uint8_t imm = getImmediateValue(instr);
                    registers[reg] = std::bitset<256>(imm);
                    break;
                }
                case ADD: {
                    uint8_t dst = getDestReg(instr);
                    uint8_t src1 = getSrcReg1(instr);
                    uint8_t src2 = getSrcReg2(instr);
                    bool carry = false;
                    std::bitset<256> result;
                    for (int i = 0; i < 256; ++i) {
                        bool b1 = registers[src1][i];
                        bool b2 = registers[src2][i];
                        uint8_t sum = b1 + b2 + carry;
                        result[i] = sum % 2;
                        carry = sum >= 2;
                    }
                    if (carry && program_base == USER_PROGRAM_BASE) {
                        printf("Прерывание: обнаружено переполнение 256-битного значения. Завершение программы.\n");
                        return;
                    }
                    registers[dst] = result;
                    break;
                }
                case OUT: {
                    uint8_t reg = getDestReg(instr);
                    printf("OUT: %s\n", bitsToDec(registers[reg]).c_str());
                    break;
                }
                case MOV_REG: {
                    uint8_t dst = getDestReg(instr);
                    uint8_t src = getSrcReg1(instr);
                    registers[dst] = registers[src];
                    break;
                }
                case JMP: {
                    uint16_t offset = getJumpOffset(instr);
                    ip = program_base + offset;
                    break;
                }
                case SLEEP: {
                    sleep_cycles = instr & 0x0FFF;
                    break;
                }
                case IN: {
                    uint8_t reg = getDestReg(instr);
                    char ch;
                    std::cin.get(ch);
                    registers[reg] = std::bitset<256>(static_cast<uint16_t>(ch));
                    break;
                }
                case PRINT: {
                    uint8_t reg = getDestReg(instr);
                    char ch = static_cast<char>(registers[reg].to_ulong() & 0xFF);
                    printf("%c", ch);
                    break;
                }
                case HALT: {
                    return;
                }
                default:
                    printf("Неизвестная инструкция: 0x%X\n", instr);
                    return;
                }
            }
        }
    };
    int main() {
        setlocale(LC_ALL, "ru");
        int fr;
        printf("Введите скорость работы виртуального компьютера (Рекомендуется 1000): ");
        std::cin >> fr;
        printf("\n\n");
        CPU cpu(fr);
        //runLoader(cpu);
        return 0;
    }
    Ответ написан
  • Почему метод push_front() работает неправильно?

    axifive
    @axifive
    Software Engineer
    Опечатка, посмотри на конструктор узла повнимательнее.
    ...
    Node(T data = T(), Node* (pnext) = nullptr) {
          this->pNext = (pNext);
    ...
    Ответ написан
    Комментировать
  • Вопрос по синтаксису Qt?

    axifive
    @axifive
    Software Engineer
    QLabel *label = new QLabel("Привет");
    Указателю присвается адресс нового объекта типа QLabel c текстом - "Привет"

    SomeClass a это переменная типа SomeClass
    SomeClass *p указатель на переменную типа SomeClass
    Ответ написан
    Комментировать