Warm tip: This article is reproduced from serverfault.com, please click

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

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

发布于 2020-12-07 11:19:17

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

例如:

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

它仅适用于r8- r15但我想用这个宏他们都rax- ,rdxrdi - rsir8r15

我应该怎么做?有内置的映射吗?

Questioner
dronte7
Viewed
0
ecm 2020-12-08 02:45:06

我将两个NASM预处理器宏放在一起,它们组合在一起就可以让你接受任何大小的寄存器名作为输入以及大小,并将其转换为给定大小的适当寄存器名。这些宏根本没有使用altreg我提到寄存器名称(在此存储在NASM手册中)。输入兼容性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(需要来自https://hg.ulukai.org/ecm/的lmacros lmacros /

在示例中使用宏的方法如下:

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