如何在宏中指定寄存器大小 (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
-rdx
、rdi
使用此宏rsi
,r8
-r15
.
我该怎么办?是否有内置映射?
我将两个 NASM 预处理器宏放在一起,它们结合在一起允许您将任何寄存器名称(任何大小)作为输入,连同大小,并将其转换为给定大小的适当寄存器名称.这些宏根本不使用我提到的 altreg
寄存器名称 (documented in the NASM manual here)。不过,可以毫不费力地添加输入 r0
到 r7
的兼容性。以下是完整的宏:
%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
我想学习一种指定通用寄存器参数大小的方法。
例如:
%macro lalala 1
mov word [buff], %1w
%endmacro
它仅适用于 r8
-r15
,但我想对所有 rax
-rdx
、rdi
使用此宏rsi
,r8
-r15
.
我该怎么办?是否有内置映射?
我将两个 NASM 预处理器宏放在一起,它们结合在一起允许您将任何寄存器名称(任何大小)作为输入,连同大小,并将其转换为给定大小的适当寄存器名称.这些宏根本不使用我提到的 altreg
寄存器名称 (documented in the NASM manual here)。不过,可以毫不费力地添加输入 r0
到 r7
的兼容性。以下是完整的宏:
%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