Dan*_*ker 13 .net clr integer specifications
将int3264 添加到64位时native int,CLR是否对32位整数进行符号扩展或零扩展?最重要的是:基于这些选择的信息?
我正在编写一个.NET编译器,并且已经完全阅读了ECMA规范,但找不到答案.
CLI支持只有在存储在其计算堆栈中的值这些类型在其业务的子集:
int32,int64,和native int.
- ECMA 335,第I节12.1:支持的数据类型
由于评估堆栈上的值没有关于其签名的信息,因此操作数的符号性重要的指令有两个变体:一个用于有符号,一个用于无符号整数.的add,sub和mul指令(那些不检查溢出)不需要,只要操作数是相同大小关心操作数的符号性,因此只有一个变种.但是,操作数并不总是相同的大小......
ECMA 335,第III节1.5:操作数类型表说明aint32和anative int可以加,减,乘和除.结果又是一个native int.在64位系统上,anative int为64位宽.
ldc.i4.0 // Load int32 0
conv.i // Convert to (64-bit) native int
ldc.i4.m1 // Load int32 -1
add // Add native int 0 and int32 0xFFFFFFFF together
Run Code Online (Sandbox Code Playgroud)
那么结果会是什么呢?请注意,根据规范,运行时不需要跟踪堆栈上值的确切类型或签名:它只知道int32,int64和native int(以及其他一些不相关的).
我会想象IntPtr和UIntPtr算术,因为它在内部表示为本机int,也会使用这种加法.但是,ILSpy表明添加一个IntPtr和一个Int32C#调用类上的重载+运算符IntPtr,它只接受一个带符号的Int32参数.
直接在CIL中执行(使用add指令)也表示整数被解释为已签名.它也应该在Mono中实现,但我找不到任何提及我的发现的参考.
添加相同bitsize的两个值时,签名无关紧要.例如,将32位-10(0xfffffff6)添加到32位10(0x0000000a)将正确地产生0.因此,addCIL(通用指令语言)中只有一条指令.
但是,当添加两个不同位数的值时,签名确实很重要.例如,将32位-10添加到64位10可以在0x100000000无符号时生成4294967296(),在签名时生成0.
CIL add指令允许添加本机整数和32位整数.本机整数可以是64位(在64位系统上).测试显示,add将32位整数视为有符号整数,并对其进行符号扩展. 这并不总是正确的,可能被视为一个错误.微软目前无法修复它.
因为溢出检查取决于操作数是被视为无符号还是有符号,所以有两种变体add.ovf:(带add.ovf符号)和add.ovf.un(无符号).但是,当将32位整数添加到本机整数时,这些变体也正确地对扩展较小的操作数进行符号扩展.
因此,根据C#的溢出检查设置,添加本机整数和无符号32位整数可能会产生不同的结果.显然,我无法弄清楚这一点是CIL语言设计中的错误或疏忽的结果.
| 归档时间: |
|
| 查看次数: |
675 次 |
| 最近记录: |