繁体   English   中英

为什么这个添加的byte *和uint无法进入更高的dword?

[英]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.

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