【问题标题】:A variable is reverting to a previous value after being assigned to with an assignment statement [duplicate]使用赋值语句分配变量后,变量正在恢复为先前的值[重复]
【发布时间】:2020-07-03 02:22:21
【问题描述】:

我正在写一个简单的chip8模拟器。

我有一个名为 programCounter(PC) 的值。

问题是,一旦我从指令 1(修改 PC)返回,PC 会返回到被方法修改之前的值。

示例

在指令1分配给PC之前,PC的值为203。

在Instruction1之后,PC的值为(0x0NNN & 0xFFFE)。

通过programCounter++,返回203而不是增量。

#include <cstdint>

constexpr auto PROGRAMSTART = 0x200;
constexpr auto GRAPHICSTART = 0xF00;
constexpr auto GRAPHICEND = 0xFFF;

//Memory
static uint8_t memory[4096]; // 0x000-0xFFF -> 0000-4095
static uint16_t stack[16];

//General Purpose Registers
static uint8_t registers[16]; //Register V0,V1,..V9,VA,VB,..,VF

//Special Purpose Register
static uint8_t specialRegisters[2];
static uint8_t stackPointer;
static uint16_t registerI;
static uint16_t programCounter = PROGRAMSTART;

//Graphic
const int WIDTH = 64;
const int HEIGHT = 32;
const int beginnningOfGraphicMemory = 0xF00;

对于指令 1NNN("https://en.wikipedia.org/wiki/CHIP-8#Opcode_table"), 这是一个简单的无条件跳转。

void Instruction1(uint16_t NNN)
{
    programCounter = (NNN & 0xFFFE); //Keeps the PC counter aligned to memory
}

int main()
{
    SetUpInterpreterText(0);
    Test();
    for (;;)
    {
        printf("Program Counter: %04x \n", programCounter);
        uint16_t byte0 = (memory[programCounter++] << 8);
        uint16_t byte1 = (memory[programCounter]);
        uint16_t instruction = byte0 + byte1; //must load data in 16bit chunks
        Decoder(instruction);
        printf("Program Counter: %04x  Data: %04x \n", programCounter, instruction);
        programCounter++;
        
    }
    return 0;
}

void Decoder(uint16_t instruction)
{
    uint16_t data = instruction & 0x0FFF; //removing the top 4 bits to make it easier
    switch (instruction >> 12)
    {
    case 0:
        Instruction0(data);
        break;
    case 1:
        Instruction1(data);
        break;
    default:
        std::cout << "Instruction Not Foud" << std::endl;
        exit(EXIT_FAILURE);
        break;
    }
}

解码器所做的只是为 16 位指令删除指令的前 4 位。例如,0x1234 发送给 1NNN 指令/方法,234 代表指令的 NNN 部分。

我反汇编了程序,根据汇编, PC 被存储在内存中,一旦我到达“programCounter++”;它从记忆中恢复。但是,对于 Instruction1,它不会将其权限写入寄存器 EAX 的内存。

我应该怎么做才能让编译器知道我希望它在我为它赋值时更新 PC 的内存位置,而不是仅仅更新寄存器?

附: 我曾尝试编写内联汇编,但我对 x86 汇编并不熟练。我似乎无法将 register_EAX 移动到值的内存位置,因此我可以强制更新值,因为 EAX 在 PC 递增之前具有正确的值。

【问题讨论】:

  • 你期望Decoder修改instruction的值吗?
  • 是的,以保持数学简单。
  • 请显示运行程序得到的输出,并解释它与预期输出的不同之处。并发布一个可编译的程序
  • static uint16_t programCounter = PROGRAMSTART; 是否在包含 2 个或更多单元的头文件中?
  • @Codelyok13 static 变量并不是真正的全局变量。它是一个static 变量,只有被编译的编译单元知道。一个真正的全局变量将在一个编译单元中声明,而在所有其他编译单元中,使用extern 关键字。您现在真正拥有的是两个(或更多)名为 programCounter 的变量,而彼此都不知道其他变量。

标签: c++ assembly static chip-8


【解决方案1】:

您有两个或多个 cpp 文件。每个组成一个编译单元。 (您包含的.h 分别成为每个编译单元的一部分;编译单元的概念在预处理完成后应用。)

静态全局变量在编译单元之间没有链接,它们对定义它们的单元是私有的。
static uint16_t programCounter 因此对于每个 cpp 文件都是本地的。

作为一般规则:

  1. 停止使用全局变量,尤其是可变变量。显式传递共享状态。使用类或结构。
  2. 特别是停止在头文件中使用可变静态变量。这太疯狂了。
  3. 当事情没有意义时检查数据的地址。

请注意,static 在类和函数中的含义与其在全局范围内的含义不同。常规全局变量已经具有静态存储类(与static 变量相同),但具有全局跨文件可见性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2017-08-09
    • 2017-07-01
    • 2013-09-13
    • 2018-11-02
    相关资源
    最近更新 更多