TL;DR
TYPE 返回“表示”类型的数据结构(如数组)的大小(以字节为单位)。
SIZEOF 返回数据结构的大小(以字节为单位)。
LENGTHOF 返回数据结构中“元素”的数量。
请注意,这些运算符可以应用于类型(例如BYTE)或标签(例如TYPE myLabel)。
对于相同的数据结构(例如记录),结果可能不同。
具体含义如下。
请注意,有类似命名的运算符 .TYPE 可用于宏中返回包含有关表达式的信息的字节位域(例如,它命名一个寄存器)。
这就是 MSDN 中编写不佳的 MASM 文档所呈现的内容。
有一个MASM 6.1 reference document here,我不知道它有多权威,但所有这个答案都是基于它。
原语
该文档将TYPE列为类似于SIZEOF的运算符
SIZEOF 和TYPE 运算符在应用于类型 时,返回该类型整数的大小。
与每种数据类型关联的大小属性为:
Data Type Bytes
BYTE, SBYTE 1
WORD, SWORD 2
DWORD, SDWORD 4
FWORD 6
QWORD 8
TBYTE 10
这里将运算符应用于类型,我相信可以将它们应用于与基元关联的标签,从而产生相同的输出。
数组
对于数组,SIZEOF 和 TYPE(和 LENGTHOF)之间的区别变得清晰:
LENGTHOF 运算符返回数组中元素的数量。 SIZEOF 运算符返回
数组定义中初始化程序使用的字节数。 TYPE 返回的大小
数组的元素。以下示例说明了这些运算符:
array WORD 40 DUP (5)
larray EQU LENGTHOF array ; 40 elements
sarray EQU SIZEOF array ; 80 bytes
tarray EQU TYPE array ; 2 bytes per element
在这种情况下,运算符与标签一起使用。
字符串
对于字符串,只要记住字符串是字节数组就足够了。
结构
对于结构,这个概念类似于数组:TYPE 是结构的大小,而SIZEOF 是与标签关联的所有结构对象的大小(MASM 考虑像 myLabel db 1, 2, 3 这样的东西是与myLabel 关联的三个字节):
SIZEOF确定的结构体大小是最后一个字段的偏移量加上最后一个字段的大小
字段,加上正确对齐所需的任何填充。
INFO STRUCT
buffer BYTE 100 DUP (?)
crlf BYTE 13, 10
query BYTE 'Filename: '
endmark BYTE 36
drives DISKDRIVES <0, 1, 1>
INFO ENDS
;One struct
info1 INFO { , , 'Dir' }
;Three structs for this label
lotsof INFO { , , 'file1', , {0,0,0} },
{ , , 'file2', , {0,0,1} },
{ , , 'file3', , {0,0,2} }
sinfo1 EQU SIZEOF info1 ; 116 = number of bytes in initializers
linfo1 EQU LENGTHOF info1 ; 1 = number of items
tinfo1 EQU TYPE info1 ; 116 = same as size
slotsof EQU SIZEOF lotsof ; 116 * 3 = number of bytes in initializers
llotsof EQU LENGTHOF lotsof ; 3 = number of items
tlotsof EQU TYPE lotsof ; 116 = same as size for structure
; of type INFO
在这种情况下,运算符与标签一起使用。
工会
对于工会来说,会发生非常相似的事情:
由SIZEOF 确定的联合大小是最长字段的大小加上所需的任何填充。
由LENGTHOF 确定的联合变量的长度等于定义的初始化程序的数量
在尖括号或花括号内。 TYPE 返回一个值,表示最长字段的类型。
DWB UNION
d DWORD ?
w WORD ?
b BYTE ?
DWB ENDS
num DWB {0FFFFh}
array DWB (100 / SIZEOF DWB) DUP ({0})
snum EQU SIZEOF num ; = 4
lnum EQU LENGTHOF num ; = 1
tnum EQU TYPE num ; = 4
sarray EQU SIZEOF array ; = 100 (4*25)
larray EQU LENGTHOF array ; = 25
tarray EQU TYPE array ; = 4
在这种情况下,运算符与标签一起使用。
记录
记录是字节、字或双字,其中单个位或位组被视为字段。
从手册中引用,但不是故意格式化为引用。
应用于记录名称的SIZEOF 和TYPE 运算符返回记录使用的字节数
记录。 SIZEOF 返回记录变量占用的字节数。你不能使用LENGTHOF
使用记录声明,但您可以将其与已定义的记录变量一起使用。 LENGTHOF 返回
记录数组中的记录数,或单个记录变量为 1。下面的例子
说明了这些要点。
; Record definition
; 9 bits stored in 2 bytes
RGBCOLOR RECORD red:3, green:3, blue:3
mov ax, RGBCOLOR ; Equivalent to "mov ax, 01FFh"
; mov ax, LENGTHOF RGBCOLOR ; Illegal since LENGTHOF can
; apply only to data label
mov ax, SIZEOF RGBCOLOR ; Equivalent to "mov ax, 2"
mov ax, TYPE RGBCOLOR ; Equivalent to "mov ax, 2"
; Record instance
; 8 bits stored in 1 byte
RGBCOLOR2 RECORD red:3, green:3, blue:2
rgb RGBCOLOR2 <1, 1, 1> ; Initialize to 00100101y
mov ax, RGBCOLOR2 ; Equivalent to "mov ax, 00FFh"
mov ax, LENGTHOF rgb ; Equivalent to "mov ax, 1"
mov ax, SIZEOF rgb ; Equivalent to "mov ax, 1"
mov ax, TYPE rgb ; Equivalent to "mov ax, 1"
在使用带有标签和类型的运算符时,这里有点不对称。
.TYPE 作为宏的运算符
这个操作符是老版本的OPATTR,返回一个字节,内容如下:
Bit Set If expression
0 References a code label
1 Is a memory variable or has a relocatable data label
2 Is an immediate value
3 Uses direct memory addressing
4 Is a register value
5 References no undefined symbols and is without error
6 Is relative to SS
7 References an external label
这有点元编程的味道,通常用于优化使用宏生成的代码。