Assembly intVal3 TBYTE 1234—汇编程序未注意到无效的TBYTE变量声明

Assembly intVal3 TBYTE 1234—汇编程序未注意到无效的TBYTE变量声明,assembly,x86,masm,Assembly,X86,Masm,我目前正在学习汇编编程,学习Kip Irvine的《汇编语言x86编程》一书 在书中,作者说 MASM使用TBYTE指令声明压缩BCD变量。 常量初始值设定项必须为十六进制,因为汇编程序 不会自动将十进制初始值设定项转换为BCD。这个 以下两个示例演示了有效和无效的方法 表示十进制-1234: intVal TBYTE 80000000000000001234h ; valid intVal TBYTE -1234 ; invalid 第二个示例无效的原因 MASM将常量编码为二进制整数而不

我目前正在学习汇编编程,学习Kip Irvine的《汇编语言x86编程》一书

在书中,作者说

MASM使用TBYTE指令声明压缩BCD变量。 常量初始值设定项必须为十六进制,因为汇编程序 不会自动将十进制初始值设定项转换为BCD。这个 以下两个示例演示了有效和无效的方法 表示十进制-1234:

intVal TBYTE 80000000000000001234h ; valid
intVal TBYTE -1234 ; invalid 
第二个示例无效的原因 MASM将常量编码为二进制整数而不是二进制整数 压缩BCD整数

我知道MASM汇编程序无法将十进制整数转换为BCD。但是我已经找到了以下编译得很好的代码(请注意,
intVal3 TBYTE 1234
被认为是无效的,但它的编译方式与有效代码一样)

为什么汇编程序没有注意到无效代码?这是一个汇编程序无法检测到的错误,需要程序员提高警惕吗

================编辑1=================

我已经检查了@PaulH建议的列表文件,这里是一个屏幕截图

从清单文件中的结果和@PaulH所说的判断,我得出了以下结论(但不确定是否完全正确):


TBYTE类型的变量将简单地将参数的二进制值(无论是80000000000000134h、-1234h还是-1234)存储到变量中。由于TBYTE类型的变量被假定为BCD整数,因此完全由程序员来确保TBYTE类型的变量被正确使用。

TBYTE类型存在的理由是具有与x87 FPU内部寄存器相同的宽度,这意味着它可以用来将其中一个寄存器的内容溢出到内存中,而不会丢失任何精度

通常,在内存中保存浮点值时,可以将其表示为单精度(32位;
DWORD
)或双精度(64位;
QWORD
)值。这很好,只是它失去了精确性。如果要在计算过程中溢出临时中间值,则通常不能通过截断该值来降低精度,因为这将影响最终结果

名称
TBYTE
仅表示此类型的值的宽度为10个字节,与值的宽度相同。(至少在默认情况下,假设没有降低FPU的精度。)

因此,
TBYTE
实际上与二进制编码十进制(BCD)没有本质上的联系。我不知道基普·欧文在说什么。您当然可以在
TBYTE
中存储BCD值,但也可以在
QWORD
DWORD
中存储较小的BCD值。顾名思义,它只是一种编码,允许您以二进制形式存储十进制数字

原因是什么

intVal3 TBYTE -1234
编译汇编是因为,对于汇编程序(MASM),您所做的只是声明一个初始化为
-1234
的10字节值。它隐式扩展
-1234
以填充10个字节,从而产生值
0xfffffffffffffb2e
,如十六进制转储中所示。与
-1234h
相同,不同的是
h
表示该值被解释为十六进制,而不是十进制

请注意,这基本上是相同的事情,如果你做了

myValue QWORD -1234
因为汇编程序将把
-1234
扩展为8字节长

正如Ped7g在一篇评论中所说,用汇编语言编程时首先要记住的是:

最后,不管您如何在源代码中指定内存内容,…操作该内存的代码定义其“含义”(类型)

汇编程序只存储字节。使用
TBYTE
,它可以存储其中的10个。通过
QWORD
,它可以存储其中的8个。使用DWORD,它存储了其中的4个。你明白了。代码如何解释这些字节取决于您,因为您必须编写这些代码


Peter Cordes指出(参见注释),x87 FPU确实有用于加载和存储BCD值的指令:和。这些

这两条指令都将
m80bcd
值作为其唯一操作数,这是一个80位BCD值,与
TYBTE
的长度相同。因此,Kip Irvine可能正在讨论
TBYTE
值的这种用法

但是,我不认为MASM会隐式地将
TBYTE
初始值设定项转换为BCD格式,因为如上所述,当您使用
TBYTE
存储扩展精度浮点值时,这将非常不方便。使用MASM或任何其他汇编器,您仍然可以自行将分配给
TBYTE
的值适当地表示为BCD或浮点,以您想要的为准


不管怎样,现在你已经听说了
FBLD
FBSTP
,你几乎可以再次忘记它们了。我不认为它们曾经被广泛使用过,而且它们现在肯定没有任何用处。即使在旧的CPU上,如原始的奔腾(P5)和奔腾II(P6),这些指令也需要大约150个时钟周期。在较新的CPU上,它们变得更慢(Skylake的吞吐量为每266个周期1个FBSTP)。因此,即使您确实希望使用80位BCD值,您最好自己编写必要的指令。(如果需要帮助,请提出一个新问题。)

如果当前基数为十进制,TBYTE将把参数解释为BCD。对不起,当前我指的是默认的(即参数上没有说明符)基数(通常总是10--decimal,除非您使用.radix指令对其进行了更改)。因此默认情况下,TBYTE将集成
myValue QWORD -1234