繁体   English   中英

__int64 在 32 位机器上?

[英]__int64 on a 32-Bit machine?

我刚刚在我的 32 位机器上尝试了 MSVC 2010 中的一些东西,发现我可以在我的程序中使用__int64 - 这确实有效!

这怎么可能?

32 位算法在 16 位系统上的工作方式相同。

在这种情况下,它使用 2 个 32 位内存地址一起组成一个 64 位数字。 加法/减法很容易,您可以按部分进行,唯一的问题是将结转从较低的部分转移到较高的部分。 对于乘法/除法,它更难(即更多指令)。

它显然很慢,比乘法的 32 位算术慢很多,但如果你需要它,它就在你身边。 当您升级到 64 位 处理器 编译器时,它会自动优化为具有更大字长的一条指令。

Visual Studio 2010 Professional 在 32 位处理器上的 64 位乘法实现,在发布模式下编译,是:

_allmul PROC NEAR

A       EQU     [esp + 4]       ; stack address of a
B       EQU     [esp + 12]      ; stack address of b

        mov     eax,HIWORD(A)
        mov     ecx,HIWORD(B)
        or      ecx,eax         ;test for both hiwords zero.
        mov     ecx,LOWORD(B)
        jnz     short hard      ;both are zero, just mult ALO and BLO

        mov     eax,LOWORD(A)
        mul     ecx

        ret     16              ; callee restores the stack

hard:
        push    ebx

A2      EQU     [esp + 8]       ; stack address of a
B2      EQU     [esp + 16]      ; stack address of b

        mul     ecx             ;eax has AHI, ecx has BLO, so AHI * BLO
        mov     ebx,eax         ;save result

        mov     eax,LOWORD(A2)
        mul     dword ptr HIWORD(B2) ;ALO * BHI
        add     ebx,eax         ;ebx = ((ALO * BHI) + (AHI * BLO))

        mov     eax,LOWORD(A2)  ;ecx = BLO
        mul     ecx             ;so edx:eax = ALO*BLO
        add     edx,ebx         ;now edx has all the LO*HI stuff

        pop     ebx

        ret     16              ; callee restores the stack

如您所见,它比普通乘法慢很多。

为什么你觉得很意外? 没有什么可以阻止编译器在 32 位机器上支持 64 位、128 位或更多位整数类型。 如果愿意,编译器甚至可以支持 57 位和 91 位类型。 实际上,在 N 位机器上支持 2N 位整数算术是一项相对容易的任务,因为典型机器的指令集在设计时通常考虑到这种功能。

32位只是一个机器字的本机大小,意味着它们可以一次处理,并不意味着更大的项目根本不能处理,它们只需要作为单独的32位单元多次处理步,以同样的方式,它们可以小于一个机器字,在这种情况下,只会处理整个机器字的一部分。

它起作用是因为 64 位整数数据类型是语言规范的一部分

该语言的编译器必须让您处理 64 位整数(当然,并获得正确的结果)。

无论您的目标是 64 位、32 位、16 位还是 8 位机器(无论编译器允许什么),您的程序都必须可以运行(并且完全相同)。

编写编译器的人有义务让它做任何需要的事情,使每个受支持的数据类型在每个目标处理器类型上工作。

支持潜在的“更高”数据类型已全部处理完毕,因此您不必自己动手。

如何?

显然,接受命令 16 位算术运算的代码并将其转换为在 16 位(或更高)处理器上运行的机器代码对于编译器来说是“容易”的工作,几乎是直接转换。 Z = X + Y可能转化为mov a,(X); add a,(Y); mov (Z),a; mov a,(X); add a,(Y); mov (Z),a; .

相反,接受命令 64 位算术运算的代码并将其转换为在 32 位(或更低)处理器上运行的机器代码则更为复杂。 编译器有更多的工作要做,一次对每个操作数的 32 位部分进行操作。 有更多方法可以完成它。

生成的机器代码可以使用多条内联指令(更大的代码,更快的执行)。 Z = X + Y可能转化为mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a; mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a; .

生成的机器代码可以调用扩展的算术子程序(代码更小,执行速度更慢)。 Z = X + Y可能会转化为mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64; mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64; .

暂无
暂无

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

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