MASM - 宏变量?

4
这是我在这里的第一个问题,希望您能帮助我! 我目前正在开发GameBoy模拟器,并希望使用MASM编写它, 为了处理CPU指令,我想创建一个变量数组,以便更轻松地访问。
以下是我想要实现的示例:
assume esi:ptr CPU_CORE
REGISTER_A equ (([esi].registers.AF AND 0F0h) SAR 3h)
REGISTER_B equ (([esi].registers.BC AND 0F0h) SAR 3h)
REGISTER_C equ (([esi].registers.BC AND 0Fh))
PARAM_TABLE [Type?] REGISTER_A
            [Type?] REGISTER_B
            [Type?] REGISTER_C
assume esi:ptr NOTHING

如果我想从PARAM_TABLE中获取一个值,应该按照以下方式进行操作:
lea esi, PARAM_TABLE
mov ecx, 1h ; just as example for accessing REGISTER_B
mov eax, [esi+ecx*[TYPE?]]
;EAX now contains the value from the hi-byte of the BC register, so: (([esi].registers.BC AND 0F0h) SAR 3h)

我的想法是创建像REGISTER_A这样的变量,以便更轻松地访问。希望您能理解我的意思。也许可以使用宏来实现这一点?


欢迎来到StackOverflow!我们通常更喜欢帖子具有正确的语法和拼写(尽管您已经纠正了拼写错误)。除此之外,这是一个不错的第一篇帖子! - Pokechu22
谢谢! 对于我犯的任何语法/拼写错误,我很抱歉,英语不是我的母语,但我会尽力改进! - BolterVi
1个回答

2

在尝试了一些事情后,我回答了自己的问题。实际上,您可以使用寄存器创建常量,例如:

REGISTER_A equ [esi+CPU_CORE.registers.A]

但是你只能像这样加载它:
mov eax, REGISTER_A ;EAX will now contain the value of the register A.

之后我发现您可以直接访问结构体的偏移量(不知道为什么以前从未使用过它)。

REGISTER_A equ CPU_CORE.registers.A

由于这个工作,我创建了一个名为 PARAM 的结构,它看起来像:

PARAM struct
  pointer DWORD  ? ;Register pointer
  flags   BYTE   ? ;BIT 0: Content Flag, BIT 1: 8 or 16 bit
  desc    DWORD  ? ;Description of the parameter
PARAM ends

我刚刚为LD R,R操作码创建了一个参数列表,看起来像这样:

PARAM_LIST_R    PARAM       <CPU_CORE.registers.B, 0, _stro('B')>
                PARAM       <CPU_CORE.registers._C, 0, _stro('C')>
                PARAM       <CPU_CORE.registers.D, 0, _stro('D')>
                PARAM       <CPU_CORE.registers.E, 0, _stro('E')>
                PARAM       <CPU_CORE.registers.H, 0, _stro('H')>
                PARAM       <CPU_CORE.registers.L, 0, _stro('L')>
                PARAM       <CPU_CORE.registers.H, 1, _stro('(HL)')>
                PARAM       <CPU_CORE.registers.A, 0, _stro('A')>

还需要一个读取寄存器的函数。

LoadParam       proc        cpu_core:DWORD, param:DWORD
    LOCAL value:DWORD
    pushad
    mov esi, cpu_core
    mov edi, param
    assume esi:ptr CPU_CORE
    assume edi:ptr PARAM
    add esi, [edi].pointer
    movzx ebx, [edi].flags
    bt ebx, 0
    test ebx, ebx
    jnc @NO_CONTENT
    movzx edx, word ptr ds:[esi]
    ;-- ADDING CPU_READ FUNCTION --;
    jmp @DONE
@NO_CONTENT:
    bt ebx, 1
    jc @GET16Bit
    movzx eax, byte ptr ds:[esi]
    jmp @DONE
@GET16Bit:
    movzx eax, word ptr ds:[esi]
@DONE:
    mov value, eax
    assume esi:ptr NOTHING
    assume edi:ptr NOTHING
    popad
    mov eax, value
    ret
LoadParam endp

该函数将CPU_CORE加载到ESI中,将PARAM加载到EDI中,并将PARAM的指针添加到CPU_CORE中。之后会测试标志位,如果设置了BIT 0,则从CPU内存中读取(例如:(HL)),否则它将仅从寄存器中获取值。BIT 1用于大小,如果设置,则该函数将读取16位寄存器(BCDEHL)或8位寄存器(BCDEHLA)。

我希望你能理解我写的内容。如果有问题,请随时问我,这是我解决问题的“最简单”方法。

如果你想知道我为什么创建了表格: 你可以通过谷歌“z80解码”来“解码”操作码以获得更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接