回想一下MS-DOS糟糕的过去,某些操作系统功能是通过在寄存器上设置高半字节和低半字节并执行中断 xx 来控制的。例如,Int 21 访问了许多文件函数。您会将高半字节设置为驱动器编号——谁将拥有超过 15 个驱动器?低半字节作为该驱动器上请求的功能等。
这是一些旧的 CPAN 代码,它使用您所描述的 pack 来设置寄存器以执行 MS-DOS 系统调用。
布莱奇!!!我一点也不怀念 MS-DOS...
- 编辑
这里是具体的源代码:在这里下载 Perl 5.00402 for DOS ,解压,
在文件 Opcode.pm 和 Opcode.pl 中,您可以看到unpack("h*",$_[0]);
这里的用法:
sub opset_to_hex ($) {
return "(invalid opset)" unless verify_opset($_[0]);
unpack("h*",$_[0]);
}
我没有一直遵循代码,但我怀疑这是从 MS-DOS 系统调用中恢复信息......
在Perl 5.8-8的 perlport 中,您有以下建议的目标字节序测试:
不同的 CPU 以不同的顺序(称为字节序)和宽度(32 位和 64 位是当今最常见的)存储整数和浮点数。当您的程序试图以二进制格式将数字从一种 CPU 架构传输到另一种时,这会影响您的程序,通常是通过网络连接“实时”传输,或者将数字存储到磁盘文件或磁带等辅助存储设备中。
冲突的存储订单使数字变得一团糟。如果小端主机(英特尔、VAX)存储0x12345678
(305419896
十进制),大端主机(摩托罗拉、Sparc、PA)将其读取为
0x78563412
(2018915346
十进制)。Alpha 和 MIPS 可以是: Digital/Compaq used/在 little-endian 模式下使用它们;SGI/Cray 在大端模式下使用它们。为了避免网络(套接字)连接中的这个问题,请使用pack
和unpack
格式n
和N
,“网络”命令。这些保证是便携的。
从 perl 5.8.5 开始,您还可以使用>
and<
修饰符来强制使用 big-endian 或 little-endian 字节顺序。例如,如果您要存储有符号整数或 64 位整数,这将非常有用。
您可以通过解压缩以本机格式打包的数据结构来探索平台的字节顺序,例如:
print unpack("h*", pack("s2", 1, 2)), "\n";
# '10002000' on e.g. Intel x86 or Alpha 21064 in little-endian mode
# '00100020' on e.g. Motorola 68040
如果您需要区分字节序架构,您可以使用以下任一变量集:
$is_big_endian = unpack("h*", pack("s", 1)) =~ /01/;
$is_little_endian = unpack("h*", pack("s", 1)) =~ /^1/;
即使在相同字节序的平台之间,不同的宽度也会导致截断。宽度较短的平台会丢失数字的上部。除了避免传输或存储原始二进制数外,这个问题没有好的解决方案。
人们可以通过两种方式解决这两个问题。总是以文本格式传输和存储数字,而不是原始二进制文件,或者考虑使用像Data::Dumper
(包含在 Perl 5.005 的标准发行版中)和Storable
(包含在 perl 5.8 中)的模块。将所有数据保存为文本可以显着简化问题。
v-strings 只能移植到v2147483647
( 0x7FFFFFFF
),这就是 EBCDIC,或者更准确地说是 UTF-EBCDIC 将走多远。
似乎unpack("h*",...)
比使用更频繁pack("h*",...)
。我确实注意到在 Perl 5.12 return qq'unpack("F", pack("h*", "$hex"))';
中使用Deparse.pm
和IO-Compress
使用pack("*h",...)
如果您想了解更多示例,请参阅Google 代码搜索列表。您可以看到pack|unpack("h*"...)
相当罕见,主要与确定平台字节序有关......