long long int怎么可能存在于32位机器上呢?

发布于 2024-09-05 21:43:44 字数 92 浏览 11 评论 0原文

我读到 GCC 支持 long long int 类型,该类型要求至少为 64 位宽。但是它如何在只有 32 位宽的 CPU 上进行数学运算呢?

I read that GCC supports the long long int type which is required to be at least 64 bits wide. But how can it make math operations with it on a CPU that is only 32 bits wide?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

清眉祭 2024-09-12 21:43:53

32 位处理器可以在单个指令中执行 32 位操作。 64 位操作需要多条指令。

机器字宽并不是对数据类型大小的限制 - 您同样可以问 8 位或 16 位机器如何对较大类型进行算术运算。显然他们可以。他们只是用更多的 CPU 时钟周期来完成它。

例如,当操作数低位字相加溢出时,进位标志被置位,如果进位标志被置位,则高位字结果为操作数高位字之和加1。 8 位机器的示例(因为作为示例更容易):

  Decimal    Binary
  1234       00000100    11010010
+ 4321       00010000  + 11100001
                |        --------
                |        10110011
                V       1 <--- carry flag 
             --------          |
           + 00010100 + 1 <----/
   ------------------------------
           = 00010101    10110011 ---> 5555 decimal --
                                                     |
= 5555  <--------------------------------------------/

对于乘法,具有硬件乘法器的机器(都是现代 32 位机器),MUL 指令将具有双字结果。例如,x86 MUL EAX,r/m3264 位 结果放入两个 32 位寄存器 EDX:EAX 中。没有硬件乘法的更简单的处理器使用多个移位和加法指令执行长乘法。无论哪种情况,双字 x 双字字 x 双字运算都需要多条指令。

当然,您可以从任意数量的字合成操作 - 因此即使是 8 位机器也可以执行 64 位操作,尽管需要更多的指令和 CPU 周期。

此外,通过扩展,没有硬件 FPU 的处理器可以执行单精度或双精度浮点数学,并且实际上在软件中可以实现任意级别的精度。

A 32-bit processor can perform 32-bit operations in a single instruction. 64-bit operations require multiple instructions.

Machine word width is not a restriction on the size of data types - you could equally ask how 8 or 16 bit machines do arithmetic on larger types. Clearly they can. They just do it in more CPU clock cycles.

For example when addition of the lower words of the operands overflows, the carry flag is set, then the high word result is the sum of the high words of the operands plus 1 if the carry flag is set. Example for an 8 bit machine (because it is easier as an example):

  Decimal    Binary
  1234       00000100    11010010
+ 4321       00010000  + 11100001
                |        --------
                |        10110011
                V       1 <--- carry flag 
             --------          |
           + 00010100 + 1 <----/
   ------------------------------
           = 00010101    10110011 ---> 5555 decimal --
                                                     |
= 5555  <--------------------------------------------/

For multiply, machines with a hardware multiplier (which is all modern 32 bit machines), the MUL instruction will have a double word result. For example x86 MUL EAX,r/m32 places the 64 bit result in two 32 bit registers EDX:EAX. Simpler processors without hardware multiply perform long-multiplication using multiple shift and addition instructions. A double-word x double-word or word x double-word operation in either case requires multiple instructions.

You can of course synthesise operations from any number of words - hence how even 8-bit machines can perform 64 bit operations, albeit with more instructions and CPU cycles.

Also by extension, processors without a hardware FPU can perform floating-point math to single or double precision, and in fact arbitrary levels of precision are possible in software.

喜爱皱眉﹌ 2024-09-12 21:43:52

最有可能的是作为一个类,而不是原生的。同样,任何编译器都可以支持任何大数字集。

Most likely as a class, not natively. same way any compiler can/could support any large number set.

无妨# 2024-09-12 21:43:51

如果您有可用的 32 位系统,那么编译和测试就很容易了。 gcc 有一个标志 -S 可以打开汇编语言输出。以下是它在我的 32 位 Intel 上产生的结果:

// read two long longs from stack into eax:edx and ecx:ebx
movl    32(%esp), %eax
movl    36(%esp), %edx
movl    24(%esp), %ecx
movl    28(%esp), %ebx
// a+b
addl    %ecx, %eax
adcl    %ebx, %edx
// a-b
subl    %ecx, %eax
sbbl    %ebx, %edx
// etc

It's easy enough to just compile and test if you have a 32-bit system accessible. gcc has a flag -S which turns on assembly language output. Here's what it produces on my 32-bit intel:

// read two long longs from stack into eax:edx and ecx:ebx
movl    32(%esp), %eax
movl    36(%esp), %edx
movl    24(%esp), %ecx
movl    28(%esp), %ebx
// a+b
addl    %ecx, %eax
adcl    %ebx, %edx
// a-b
subl    %ecx, %eax
sbbl    %ebx, %edx
// etc
别闹i 2024-09-12 21:43:50

说架构是 32 位(或 64 位或其他)通常只是处理器能力的近似值。通常你只用这个数字来引用指针的宽度,算术可能会有很大不同。例如,x86 架构具有 32 位指针,大多数算术在 32 位寄存器中执行,但它也对一些基本的 64 位操作具有本机支持。

另外,您不应该认为标准整数类型具有某些规定的宽度。特别是 long long 至少为 64 位,但可能更宽。如果您想确定宽度,请使用 typedef int32_t、int64_t。

如果您想知道 gcc(或任何其他编译器)使用 long long 做什么,您必须查看特定目标平台的规范

Saying an architecture is 32 bit (or 64 or whatever) is usually only an approximation of what the processor is capable of. Usually you only refer to the width of pointers with that number, arithmetic might be quite different. E.g the x86 architecture has 32 bit pointers, most arithmetic is performed in 32 bit registers, but it also has native support for some basic 64 bit operations.

Also you shouldn't follow the impression that the standard integer types have some prescribed width. In particular long long is at least 64 bit but may be wider. Use the typedefs int32_t, int64_t if you want to be portably sure about the width.

If you want to know what gcc (or any other compiler) does with long long you have to look into the specification for your particular target platform

命比纸薄 2024-09-12 21:43:49

在内部,类型由高位字和低位字表示,例如:

struct long
{
  int32 highWord;
  uint32_t lowWord;
}

编译器需要知道它是 32 位还是 64 位环境,然后选择数字的正确表示 - 如果是 64 位,则可以本地完成,如果是 32 位,编译器必须处理高/低字之间的数学运算。

如果您查看 math.h,您可以看到用于此目的的函数,并自己使用它们。另外,请注意小端和大端之间的区别(参见 wiki ),使用情况取决于操作系统。

Internally, the type is represented by a high-word and a low-word, like:

struct long
{
  int32 highWord;
  uint32_t lowWord;
}

The compiler needs to know if it is a 32bit or 64bit environment and then selects the right reprenstations of the number - if it is 64bit, it can be done natively, if it is 32bit, the compiler has to take care of the math between the high/lowword.

If you have a look in math.h, you can see the functions used for this, and use them yourself. On an additional note, be aware of the difference between little-endian and big-endian (see wiki), the usage depends on the operating system.

最后的乘客 2024-09-12 21:43:48

编译器将综合使用多个 CPU 指令来执行运算的数学运算(或使用函数调用)。例如,加法运算将添加long long值的低位分量(低位字),然后将该运算的进位送入高位的加法运算中。 长长的话语

因此,以下 C 代码:

long long a;
long long b;
long long c;

// ...
c = a + b;

可能由如下所示的指令序列表示:

mov eax, [a.low]   ; add the low order words
add eax, [b.low]

mov edx, [a.high]  ; add the high order words, 
adc edx, [b.high]  ; including the carry 

mov [c.low], eax
mov [c.high], edx

如果您考虑一下,8 和 16 位系统的编译器必须对 16 和/或 32 位值长执行此类操作在long long出现之前。

The compiler will synthesize math operations (or use function calls) that use more than one CPU instruction to perform the operation. For example, an add operation will add the low order components (the low words) of the long long values and will then take the carry out of that operation and feed it into an add operation on the high order words of the long long.

So the following C code:

long long a;
long long b;
long long c;

// ...
c = a + b;

might be represented by an instruction sequence that looks something like:

mov eax, [a.low]   ; add the low order words
add eax, [b.low]

mov edx, [a.high]  ; add the high order words, 
adc edx, [b.high]  ; including the carry 

mov [c.low], eax
mov [c.high], edx

And if you consider for a moment, compilers for 8 and 16 bits systems had to do this type of thing for 16 and/or 32-bit values long before long long came into being.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文