简体   繁体   English

为什么硬件寄存器访问是通过无符号数据类型

[英]Why hardware register access is through unsigned datatype

I was going through some examples and unsigned is used in all of them. 我正在阅读一些例子,并且在所有这些例子中都使用了unsigned。 Is it safe to use int type, if used properly? 如果使用正确,使用int类型是否安全? Like in the example below, 0x12345678 address will have 0xFFFFFFFF written to it irrespective of ptr being defined as signed or unsigned. 与下面的示例类似,0x12345678地址将写入0xFFFFFFFF,而不管ptr被定义为有符号还是无符号。

volatile unsigned int* ptr = (volatile unsigned int* ) 0x12345678; 

*ptr = 0xFFFFFFFF;

Why is it safe to use unsigned instead of signed for register access? 为什么使用unsigned而不是signed来进行寄存器访问是否安全?

I think that unsigned C arithmetic is closer to machine registers arithmetic. 我认为无符号C算法更接近机器寄存器算术。 It is because the C language definition says that, if signed integer arithmetic operation results into a number not fitting the given type (overflow) then the actual result of the operation is undefined. 这是因为C语言定义说,如果有符号整数算术运算结果为不符合给定类型(溢出)的数字,则操作的实际结果是未定义的。 So it can be anything. 所以它可以是任何东西。 While in unsigned arithmetic: 在无符号算术中:

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type. 涉及无符号操作数的计算永远不会溢出,因为无法用结果无符号整数类型表示的结果以比模式生成的无符号整数类型所表示的最大值大1的数量减少。

which is the same as happens in machine registers. 这与机器寄存器中发生的情况相同。

Your example is another case, the line: 你的例子是另一种情况,即:

*ptr = 0xFFFFFFFF;

creates a constant 0xFFFFFFFF of type unsigned long int . 创建一个类型为unsigned long int的常量0xFFFFFFFF The type is unsigned instead of int because the value is bigger than the maximum integer value. 类型是unsigned而不是int因为该值大于最大整数值。 If the variable ptr was of type int* , then the compiler would need to convert unsigned to signed before the assignment. 如果变量ptr的类型为int* ,则编译器需要在赋值之前将unsigned转换为signed This would cause overflow and the result of this assignment would be undefined. 这会导致溢出,并且此赋值的结果将是未定义的。 Although I do not know a compiler which would generate any arithmetic operation when casting from unsigned to int . 虽然我不知道在从unsignedint时会生成任何算术运算的编译器。

If ptr was defined as int* , and you would want to be correct, then your line should be: 如果ptr被定义为int* ,并且你想要正确,那么你的行应该是:

*ptr = -1;

Most hardware registers are either not arithmetic objects (they may be bitfields rather than semantically numeric), or if they do represent a number it is unusual for them to be semantically signed ( a negative value would make no sense for a baud rate divisor for example). 大多数硬件寄存器要么不是算术对象(它们可能是位字段而不是语义数字),或者如果它们确实代表一个数字,那么对它们进行语义签名是不常见的(例如,负值对波特率除数没有意义) )。

So often, while a signed type may make no difference at the low level, it makes no semantic sense at the high level. 通常,虽然签名类型在低级别上可能没有区别,但它在高级别上没有语义意义。

Critically perhaps, the >> operator, often used in processing hardware register values, has implementation defined behaviour for signed types; 或许,通常用于处理硬件寄存器值的>>运算符具有已签名类型的实现定义行为; so to avoid mixed sign operations and the associated implicit conversions introducing errors, you should use unsigned in most cases. 因此,为了避免混合符号操作以及引入错误的关联隐式转换,您应该在大多数情况下使用unsigned。

I would suggest that unless the hardware register is semantically signed numeric, then you should use unsigned consistently for not just the registers, but also operands in expressions with register operands. 我建议除非硬件寄存器是语义符号数字,否则你应该不仅对寄存器一致地使用无符号,而且还要在带有寄存器操作数的表达式中使用操作数。

The answer is simple: the value you use is unsigned (meaning that the literal 0xFFFFFFFF is unsigned). 答案很简单:您使用的值是无符号的(意味着文字0xFFFFFFFF是无符号的)。 You could assign it to any data type that can hold it - even a float or double could be used. 您可以将其分配给任何可以保存它的数据类型 - 甚至可以使用float或double。 But, you want to store an unsigned value and see it as an unsigned (for example, the %x specifier of printf, that prints a hex value, casts it to unsigned). 但是,您希望存储无符号值并将其视为无符号值(例如,printf的%x说明符,它打印十六进制值,将其强制转换为无符号值)。 So, if your data is in the entire process unsigned, why not have the data type of its container unsigned too? 那么,如果您的数据在整个过程中未签名,为什么不将其容器的数据类型也取消签名呢?

The processor register you write to doesn't know or care how your compiler defines the value, so long as the correct value is written. 您写入的处理器寄存器不知道或不关心编译器如何定义值,只要写入正确的值即可。 I upvoted the question because you tried to find an answer before posting. 我赞成这个问题,因为你试图在发布之前找到答案。

As stated before, being unsigned or signed is stored the same way in the hardware register. 如前所述,未签名或签名以相同的方式存储在硬件寄存器中。 It is the higher level c that interprets this value as either being a signed or unsigned number. 更高级别的c将此值解释为有符号或无符号数。

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

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