如何在宏中指定寄存器大小 (b/w/d)

How to specify the register size (b/w/d) in a macro

我想学习一种指定通用寄存器参数大小的方法。

例如:

%macro lalala 1
  mov word [buff], %1w
%endmacro

它仅适用于 r8-r15,但我想对所有 rax-rdxrdi 使用此宏rsi,r8-r15.

我该怎么办?是否有内置映射?

我将两个 NASM 预处理器宏放在一起,它们结合在一起允许您将任何寄存器名称(任何大小)作为输入,连同大小,并将其转换为给定大小的适当寄存器名称.这些宏根本不使用我提到的 altreg 寄存器名称 (documented in the NASM manual here)。不过,可以毫不费力地添加输入 r0r7 的兼容性。以下是完整的宏:

    %imacro regindexdef 2.nolist
%push
 %define _%1 256
 %assign %$size 0
 %assign %$exit 0
 %rep 5
  %ifn %$exit
   %if %$size == 0
    %define %$regnames "ah  ch  dh  bh  "
   %elif %$size == 1
    %define %$regnames "al  cl  dl  bl  spl bpl sil dil r8b r9b r10br11br12br13br14br15b"
   %elif %$size == 2
    %define %$regnames "ax  cx  dx  bx  sp  bp  si  di  r8w r9w r10wr11wr12wr13wr14wr15w"
   %elif %$size == 4
    %define %$regnames "eax ecx edx ebx esp ebp esi edi r8d r9d r10dr11dr12dr13dr14dr15d"
   %elif %$size == 8
    %define %$regnames "rax rcx rdx rbx rsp rbp rsi rdi r8  r9  r10 r11 r12 r13 r14 r15 "
   %endif
   %assign %$index 0
   %rep 16
    %ifn %$exit
     %substr %$reg %$regnames %$index * 4 + 1, 4
     %deftok %$reg %$reg
     %ifnempty %$reg
      %ifidni %$reg, %2
       %assign _%1 %$index
       %assign %$exit 1
       %exitrep
      %endif
     %endif
    %endif
    %assign %$index %$index + 1
   %endrep
   %if %$exit
    %exitrep
   %endif
   %assign %$size !%$size + %$size * 2
  %endif
 %endrep
 %ifn %$exit
  %error Invalid register name: %2
 %endif
%pop
    %endmacro


    %imacro regsizedef 3.nolist
%push
 %define _%1 invalidregister
 %assign %$size 0
 %assign %$highbyte 0
 %ifidni %2, byte
  %assign %$size 1
 %elifidni %2, highbyte
  %assign %$size 1
  %assign %$highbyte 1
 %elifidni %2, word
  %assign %$size 2
 %elifidni %2, dword
  %assign %$size 4
 %elifidni %2, qword
  %assign %$size 8
 %else
  %assign %$size %2
 %endif
 %if %$size == 0
  %error Invalid register size: %2
 %else
  %ifnnum %3
   %error Invalid register number: %3
  %elif (%3) >= 16
   %error Invalid register number: %3
  %elif (%3) < 0
   %error Invalid register number: %3
  %else
   %if %$size == 1 && %$highbyte
    %define %$regnames "ah  ch  dh  bh  "
   %elif %$size == 1
    %define %$regnames "al  cl  dl  bl  spl bpl sil dil r8b r9b r10br11br12br13br14br15b"
   %elif %$size == 2
    %define %$regnames "ax  cx  dx  bx  sp  bp  si  di  r8w r9w r10wr11wr12wr13wr14wr15w"
   %elif %$size == 4
    %define %$regnames "eax ecx edx ebx esp ebp esi edi r8d r9d r10dr11dr12dr13dr14dr15d"
   %elif %$size == 8
    %define %$regnames "rax rcx rdx rbx rsp rbp rsi rdi r8  r9  r10 r11 r12 r13 r14 r15 "
   %else
    %define %$regnames ""
   %endif
   %substr %$reg %$regnames (%3) * 4 + 1, 4
   %deftok %$reg %$reg
   %ifempty %$reg
    %error Invalid register type selected
   %else
    %xdefine _%1 %$reg
   %endif
  %endif
 %endif
%pop
    %endmacro

以下是一些使用宏的有效示例:

    bits 64

regsizedef REG, 2, 0
    mov _REG, 1234h
    ; mov to ax
regsizedef REG, 4, 0
    mov _REG, 12345678h
    ; mov to eax
regsizedef REG, qword, 0
%warning REG=>>_REG<<
; rax
regsizedef REG, highbyte, 2
%warning REG=>>_REG<<
; dh

regindexdef INDEX, rdi
regsizedef REG, word, _INDEX
    mov _REG, 1234h
    ; mov to di

regindexdef INDEX, cx
regsizedef REG, qword, _INDEX
%warning REG=>>_REG<< INDEX=>>_INDEX<<
; reg rcx, index 1

我还上传了一个包含宏、有效测试用例和一些无效测试用例的文件:https://ulukai.org/ecm/20201207.txt (needs lmacros from https://hg.ulukai.org/ecm/lmacros/)

以下是在您的示例中使用宏的方法:

%macro lalala 1
regindexdef INDEX, %1
regsizedef REG, word, _INDEX
  mov word [buff], _REG
%endmacro