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

时间:2014-01-07 01:10:08

标签: c char cpu-registers

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

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

6 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

字符受integer promotion约束。只要它们与其他非char整数值组合,它们就会被符号扩展为int,如果它们与这些操作数组合,它们甚至会浮动。

确保不要不正确地使用结果。当您将int强制转换为char时,您隐含地接受丢失较高有效位的风险。

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

答案 3 :(得分:0)

通常,无符号数量用零填充,有符号数量为sign-extended

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

在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,零值保留值相同,签名字符的符号位。