MASM - Макропеременная?

Это мой первый вопрос, и я надеюсь, что вы сможете мне помочь! В настоящее время я работаю над эмулятором GameBoy и хочу написать его на MASM, для обработки инструкций процессора, я хочу создать массив с переменными, чтобы мне было легче получить к нему доступ.

Вот пример того, чего я хочу достичь:

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, чтобы упростить доступ к ним. Надеюсь, ты меня понимаешь. Может быть, это можно сделать с помощью макросов?

1 ответ

Поэтому я отвечаю на свой вопрос, связав некоторые вещи. Действительно, вы можете создавать константы, используя такие регистры, как:

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 установлено, что он читает из памяти процессора (как пример: (HL)), если он не установлен, он просто получит значение из регистра. BIT 1 для размера, если он установлен, функция будет читать 16-битный регистр (BC, DE, HL) или 8-битный регистр (B, C, D, E, H, L, A).

Я надеюсь, вы понимаете, что я написал. Если у вас есть какие-либо вопросы, не стесняйтесь задавать, это самый простой способ решить мою проблему.

Если вам интересно, почему я создал таблицу: вы можете "декодировать" коды операций для получения дополнительной информации в Google "z80 decoding".

Другие вопросы по тегам