Определение типа операнда на этапе компиляции (MASM 4.0)
Известно, что в MASM 4.0 имеются несколько операторов, которые позволяют на этапе компиляции статически определить тип операнда, его длину (в количестве элементов) и размер (в байтах).
Есть только одно «но», операторы
type,
length и
size применимы только к описанным именам, а с регистрами они «беспомощны»:
type ax = abs.
Тем не менее, часто бывает, что в статически настраиваемом макроблоке необходимо работать не только с именами (константы, адреса, метки), но и с регистрами.
Причем дополнительный оператор
.type также отказывается работать с регистрами, причисляя их к прочим константным выражениям.
Для решения этой задачи ниже предлагается макроопределение, позволяющее на этапе компиляции определеить «класс» операнда (регистр, метка, адрес, константа) и размер в байтах.
В случае констант под «размером» понимается минимальное количество байт, необходимое для представления значения константного выражения.
Для начала вводится блок описания констант перечисления типов:
; константное выражение --- это целое число, имя константы, к.в., имя сегмента, имя поля, имя структуры)
; биты размерности
SZ_BYTE equ 1
SZ_WORD equ 2
SZ_DWORD equ 4
; биты типа
TP_CNST equ 1 shl 8
TP_ADDR equ 1 shl 9
TP_LABEL equ 1 shl 10
TP_REG equ 1 shl 11
; регистровые биты
TP_COMREG equ 1 shl 12
TP_INDXREG equ 1 shl 13
TP_SEGREG equ 1 shl 14
Далее, макроопределение
TYPE_:
; Определение размера op в байтах, где op --- имя регистра, адреса памяти, или константы
; Если op имя регистра, в typ возвращается его тип: общего назначения (1) или сегментный (2).
TYPE_ macro op, typ
typ = type op
ife typ
;; op оказался регистром, константой, именем сегмента, именем структуры или именем поля записи
SIZETCOMP op, typ, TP_REG+TP_COMREG+SZ_BYTE, <A,a,B,b,C,c,D,d>, <H,h,L,l>
SIZETCOMP op, typ, TP_REG+TP_COMREG+SZ_WORD, <A,a,C,c,D,d>, <X,x>
SIZETCOMP op, typ, TP_REG+TP_COMREG+TP_INDXREG+SZ_WORD, <S,s,D,d>,<I,i>
SIZETCOMP op, typ, TP_REG+TP_COMREG+SZ_WORD, <S,s>, <P,p>
SIZETCOMP op, typ, TP_REG+TP_COMREG+TP_INDXREG+SZ_WORD, <B,b>, <X,x,P,p>
SIZETCOMP op, typ, TP_REG+TP_SEGREG+SZ_WORD, <C,c,D,d,E,e,S,s>, <S,s>
ife typ
;; если op не имя регистра, значит константа
if op LT 256
typ = TP_CNST + SZ_BYTE
else
typ = TP_CNST + SZ_WORD
endif
endif
else
if typ LT 0
typ = -typ + TP_LABEL
else
typ = typ + TP_ADDR
endif
endif
endm
SIZETCOMP macro reg, typ, typ_, HighPart, LowPart
irp highchar, <HighPart>
irp lowchar, <LowPart>
ifidn <reg>, <highchar&&&lowchar>
typ = typ_
endif
endm
endm
endm
Таким образом получается, что размер операнда в байтах кодируется в младшем байте результата
typ, а «класс» операнда — в старшем байте.
Макроопределение различает метки, адреса, регистры (общего назначения, индексные и сегментные), константные выражения.