intVal3 TBYTE 1234 - 汇编程序没有注意到TBYTE变量声明无效

时间:2017-06-28 03:40:33

标签: assembly x86 masm

我目前正在学习汇编编程,遵循Kip Irvine的“汇编语言x86编程”一书。

在书中,作者陈述

  

MASM使用TBYTE指令声明打包的BCD变量。   由于汇编程序,常量初始值设定项必须为十六进制   不会自动将十进制初始值设定项转换为BCD。该   以下两个例子展示了有效和无效的方式   代表十进制-1234:

#!/bin/sh
/path/to/actual_script "$@" | perl -pe's/.../.../g'
     

第二个例子无效的原因   是MASM将常量编码为二进制整数而不是a   打包BCD整数。

据我所知,MASM汇编程序无法将十进制整数转换为BCD。但我提出了以下编译得很好的代码(注意intVal TBYTE 80000000000000001234h ; valid intVal TBYTE -1234 ; invalid 假设无效,但它编译就像有效代码一样)

intVal3 TBYTE 1234

为什么汇编程序忽略了无效代码?这是汇编程序无法检测到的错误,需要程序员保持警惕吗?

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

我已按照@PaulH的建议检查了列表文件,这是一个截图

enter image description here

从列表文件的结果和@PaulH所说的结果来看,我得出了以下结论(尽管不完全正确):

TBYTE类型的变量将解释简单存储参数的二进制值(无论是80000000000000001234h,-1234h还是-1234)到变量中。因为TBYTE类型的变量被认为是用作BCD整数,所以完全由程序员来确保TBYTE类型的变量被正确使用。

1 个答案:

答案 0 :(得分:5)

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

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

名称TBYTE仅表示此类型的值为10字节宽,与is used internally for floating-point values on the x87的宽度相同。 (默认情况下,至少,假设您没有降低FPU的精度。)

因此,TBYTE实际上与二进制编码的十进制(BCD)没有任何关系。我不知道Kip Irvine在那里谈论什么。您当然可以在TBYTE中存储BCD值,但您也可以在QWORDDWORD中存储较小的BCD值。顾名思义,BCD只是一种编码,允许您以二进制形式存储十进制数字。

原因

intVal3 TBYTE -1234

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

请注意,如果你这样做,这基本上是相同的。

myValue QWORD -1234

因为汇编程序将-1234扩展为8个字节。

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

  

最后,如何在源中指定内存内容无关紧要......操作该内存的代码定义其“含义”(类型)。

汇编程序只存储字节。使用TBYTE,它存储了10个。使用QWORD,它存储了8个。使用DWORD,它会存储其中的4个。你得到了照片。您的代码如何解释这些字节取决于您,因为您必须编写该代码。

Peter Cordes指出(见评论)x87 FPU确实有用于加载和存储BCD值的指令:FBLDFBSTP。这些can be used as a slow way to turn a binary integer into decimal digits

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

但是,我不相信MASM会将TBYTE初始值设定项隐式转换为BCD格式,因为当您使用TBYTE存储时,非常不方便扩展精度浮点值,如上所述。使用MASM或任何其他汇编程序,您仍然可以自己将分配给TBYTE的值恰当地表示为BCD或浮点值,无论您想要哪一个。

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