我想学习一种指定常规寄存器参数大小的方法。
例如:
%macro lalala 1
mov word [buff], %1w
%endmacro
它仅适用于r8
- r15
,但我想用这个宏他们都rax
- ,rdx
,,rdi
- 。rsi
r8
r15
我应该怎么做?有内置的映射吗?
我将两个NASM预处理器宏放在一起,它们组合在一起就可以让你接受任何大小的寄存器名作为输入以及大小,并将其转换为给定大小的适当寄存器名。这些宏根本没有使用altreg
我提到的寄存器名称(在此存储在NASM手册中)。输入兼容性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(需要来自https://hg.ulukai.org/ecm/的lmacros lmacros /)
在示例中使用宏的方法如下:
%macro lalala 1
regindexdef INDEX, %1
regsizedef REG, word, _INDEX
mov word [buff], _REG
%endmacro