繁体   English   中英

char数据类型如何在32位寄存器中表示?

[英]How does char data type represent in 32-bit registers?

我知道int和其他32位数据类型适合寄存器。 但是我不明白当我们的数据类型(如1字节的char)小于32位时会发生什么。 就像在char示例中一样,24位的其余部分会发生什么? 是否填充全0? 用一个词代表它不是太小吗?

更新:假设我有一个带有char变量的C程序。 它如何代表注册?

如果CPU允许分段寄存器访问(例如,字,字节),它可能只使用字节子寄存器。 如果CPU严格为32位,则字节进入0-7位。 根据目标使用情况,如果目标代码与寄存器一起工作,它可能会或可能不会将其余部分屏蔽为0.(AND reg,0x000000FF)。 变量太多,开放性很强,给你一个黑色的答案。

利用0xFF作为字节寄存器,0x000000FF作为d字寄存器,如果它们具有单独的字节和双字段,则使用它们的操作码相同。 除非它们是特定于位的操作,例如“如果高位设置分支”,或位旋转/移位。 如果签名,0xFF将扩展为0xFFFFFFFF(或0x83至0xFFFFFF83)

编辑到更新:表示寄存器中的字符的C实际上将其余部分归零,这取决于编译器在设置位0-7之前可能首先将寄存器归零,或者它可以如上所述执行。 签名时,符号位需要扩展0寄存器,NEG并设置0-7。 有些CPU甚至有明确的用于符号扩展的操作。

这取决于它是如何放在那里的。 容器的数据永远不会“太小”。

字符需要进行整数提升 一旦它们与其他非char整数值组合,它们就会被符号扩展为int ,如果它们与这些操作数组合,则甚至是浮点符号。

你应该确保不要不正确地使用结果。 当你将一个int转换回一个char ,你隐含地接受了丢失高位的风险。

至于特定编译器如何处理它,这取决于编译器设计者。 在Pentium monstruous体系结构中,您可以使用寄存器的char版本,但在更常规的处理器上,如果参与进一步的计算,则可以更方便地对char进行签名扩展以规范化其值。

通常,无符号数量用零填充,有符号数量用符号扩展

C中的char类型是一种特殊情况,因为标准允许它是有符号或无符号的(并且一些编译器提供了让开发人员选择的选项)。 这允许编译器使用最有效的方法。

C语言没有寄存器,因此程序员看不到这样的表示。 如果使用较宽寄存器的一部分,则未使用的部分可以包含其他数据,或者它可以具有零。 重要的是正确转换操作char值(或任何其他值)的正确程序,以便生成正确的输出和任何其他外部可见行为。

如果使用32位寄存器来保存8位字符,并且未清除未使用的位,则生成的机器代码必须注意,例如,不要将剩余的24位包含在比较结果中(char_a == char_b) ,因为那么两个相等的char将错误地比较不等。 生成的机器代码必须告诉处理器使用一些只查看最低有效8位的字节宽度操作。 有些架构有这样的东西,因此生成代码可能更容易,这些代码将内存中的char表示转换为寄存器中的完整32位值(符号扩展,如果它们是有符号的)。

这实际上取决于给定目标处理器的方便和高效。

在x86上,子寄存器有各自的硬件名称。 eax的下半部分是al。 你甚至可以在同一个寄存器上分配2个字符:eax是[16位| 啊| 人]。 所以有可能通过al / ah / bl / bh来处理字符等等都有高位垃圾。 但是gcc更喜欢执行非常奇怪的事情:

char foo(char c) {
    return c+(char)1;
}

gcc -O2-m32 -S:

foo:
    pushl   %ebp
    movl    %esp, %ebp
    movzbl  8(%ebp), %eax
    popl    %ebp
    addl    $1, %eax
    movsbl  %al,%eax
    ret

movzbl表示用零扩展,movsbl表示用符号位扩展。

第一次将输入扩展为0,然后执行+1,然后使用低字节(al)符号位扩展结果(eax)。 所以它使用零/符号位扩展。 对于unsigned char,零离开值相同,对于signed char,则为sign位。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM