[英]Why does this addition of byte* and uint fail to carry into the higher dword?
现在提交Microsoft Connect ; 如果您觉得需要修理请立即投票。 我也简化了测试用例:
byte* data = (byte*) 0x76543210;
uint offset = 0x80000000;
byte* wrong = data + offset;
byte* correct = data + (uint) 0x80000000;
// "wrong" is now 0xFFFFFFFFF6543210 (!)
// "correct" is 0xF6543210
看看IL,就我所知,C#编译器做的一切都正确,错误在于JITter。
原始问题 :这里发生了什么?
byte* data = (byte*)Marshal.AllocHGlobal(0x100);
uint uioffset = 0xFFFF0000;
byte* uiptr1 = data + uioffset;
byte* uiptr2 = data + (uint)0xFFFF0000;
ulong uloffset = 0xFFFF0000;
byte* ulptr1 = data + uloffset;
byte* ulptr2 = data + (ulong)0xFFFF0000;
Action<string, ulong> dumpValue =
(name, value) => Console.WriteLine("{0,8}: {1:x16}", name, value);
dumpValue("data", (ulong)data);
dumpValue("uiptr1", (ulong)uiptr1);
dumpValue("uiptr2", (ulong)uiptr2);
dumpValue("ulptr1", (ulong)ulptr1);
dumpValue("ulptr2", (ulong)ulptr2);
此测试需要针对x64平台的64位操作系统。
输出:
data: 000000001c00a720 (original pointer) uiptr1: 000000001bffa720 (pointer with a failed carry into the higher dword) uiptr2: 000000011bffa720 (pointer with a correct carry into the higher dword) ulptr1: 000000011bffa720 (pointer with a correct carry into the higher dword) ulptr2: 000000011bffa720 (pointer with a correct carry into the higher dword) ^ look here
那么这是一个错误还是我搞砸了什么?
(正在建设中的答案)
我检查了发出的x64 asm,这些是我的观察结果:
基指针:
data:
00000000024539E0
带正确携带的指针:
data + (uint)0xFFFF0000:
00000001024439E0
拆卸说明:
byte* ptr2 = data + ((uint)0xFFFF0000); // redundant cast to be extra sure
00000084 mov ecx,0FFFF0000h
00000089 mov rax,qword ptr [rsp+20h]
0000008e add rax,rcx
00000091 mov qword ptr [rsp+38h],rax
携带不正确的指针:
data + offset:
00000000024439E0
拆卸说明:
uint offset = 0xFFFF0000;
0000006a mov dword ptr [rsp+28h],0FFFF0000h
byte* ptr1 = data + offset;
00000072 movsxd rcx,dword ptr [rsp+28h] ; (1)
00000077 mov rax,qword ptr [rsp+20h]
0000007c add rax,rcx
0000007f mov qword ptr [rsp+30h],rax
指令(1)将unsigned int32转换为带符号扩展(bug或feature?)的带符号long。 因此rcx
包含0xFFFFFFFFFFFF0000
,而它应该包含0x00000000FFFF0000
以使加法正常工作。
并根据64位算术:
0xFFFFFFFFFFFF0000 +
0x00000000024539E0 =
0x00000000024439E0
添加溢出确实。
我不知道这是一个错误或预期的行为,我会在尝试给出任何结论之前检查SSCLI。 编辑:见Ben Voigt的回答。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.