Известно, что в 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, а «класс» операнда — в старшем байте. Макроопределение различает метки, адреса, регистры (общего назначения, индексные и сегментные), константные выражения.