当前位置: 首页 > 知识库问答 >
问题:

c编译器如何处理无符号和有符号整数?为什么无符号和有符号算术运算的汇编代码是相同的?

毕胡非
2023-03-14

我在看的书:CS-app 2。c有无符号和有符号的int类型,并且在大多数架构中使用二进制补码算法来实现有符号值;但是学了一些汇编代码之后,发现很少有指令区分无符号和有符号。所以我的问题是:

>

  • 区分有符号和无符号是编译器的责任吗?如果是,它是如何做到的?

    谁实现两个补码算法——CPU还是编译器?

    添加更多信息:

    在学习了更多的指令后,实际上有一些指令区分有符号和无符号,例如setg、seta等。此外,CF和OF分别适用于无符号和无符号。但是大多数整数算术指令对无符号和有符号是一样的,例如。

    int s = a + b
    

    unsigned s = a + b
    

    生成相同的指令。

    所以当执行< code>ADD s d时,CPU应该把s

    P. S我正在使用x86和gcc

  • 共有3个答案

    赫连永怡
    2023-03-14

    对于大多数算术/逻辑运算,不需要区分有符号和无符号整数。通常只需要在打印、零/符号扩展或比较值时考虑符号。事实上,CPU对值的类型一无所知。4字节的值只是一系列位,除非用户指出这是一个浮点数、一个由4个字符组成的数组、一个无符号整数或有符号整数等,否则它没有任何意义。例如,当打印一个char变量时,根据指示的类型和输出属性,它将打印出字符、无符号整数或有符号整数。程序员有责任向编译器展示如何处理该值,然后编译器将发出处理该值所需的正确指令。

    王庆
    2023-03-14

    这很简单。像加法和减法这样的运算不需要对二进制补码算法中的有符号类型进行任何调整。只需进行一个头脑实验,想象一个算法只使用以下数学运算:

    • 递增 1
    • 递减一
    • 与零比较

    加法只是从一堆中一个接一个地获取项目,然后把它们放在另一个堆中,直到第一个堆是空的。减法是一次从它们两个中获取,直到减去的那个是空的。在模块化算术中,你只需将最小值视为最大值加1,它就起作用了。二的补码只是一种模块化算术,其中最小值为负。

    如果您想看到任何差异,我建议您尝试对溢出不安全的操作。一个例子是比较(<code>a

    编译器是否有责任区分签名和未签名?如果是,它是如何做到的?

    通过在需要时生成不同的程序集。

    谁实现两个补码算法——CPU还是编译器?

    这是一个很难回答的问题。二进制补码可能是在计算机中处理负整数的最自然方法。对于带有溢出的 two's 补码,大多数操作与对带有溢出的无符号整数的操作相同。符号可以从单个位中提取。从概念上讲,比较可以通过减法(与符号无关)、符号位提取和与零的比较来完成。

    不过,正是CPU的算术特性允许编译器以2的补码进行计算。

    无符号s=a b

    请注意,这里计算加号的方式不取决于结果的类型。Insead它取决于等号右边变量的类型。

    所以在执行 ADD s d 时,CPU 是否应该处理

    CPU指令不知道类型,这些类型只能由编译器使用。此外,添加两个无符号数字和添加两个有符号数字没有区别。有两个指令用于相同的操作是愚蠢的。

    尹赞
    2023-03-14

    在许多情况下,有符号和无符号操作在机器级别上没有区别,这仅仅是位模式的解释问题。例如,考虑下面的4位字操作:

    Binary Add  Unsigned   2's comp
    ----------  --------   --------
      0011          3         3
    + 1011       + 11       - 5
    -------     --------   --------
      1110         14        -2  
    -------     --------   --------
    

    有符号和无符号操作的二进制模式是相同的。请注意,减法只是负值的加法。当执行SUB操作时,右侧操作数是两个互补的(反转位和增量),然后相加(负责的ALU电路是加法器);不是在你理解的指令级别,而是在逻辑级别,尽管有可能在没有SUB指令的情况下实现机器,并且仍然执行减法,尽管是在两个指令而不是一个指令中。

    根据类型,某些操作确实需要不同的指令,一般来说,编译器有责任生成适当的代码 - 体系结构差异可能适用。

     类似资料:
    • 我正在使用MASM 14.0进行组装,我与下面代码的输出混淆。 这两个算术运算都是在无符号整数255和127上完成的。 然而,CPU将第一个操作255视为无符号整数,并设置进位标志,当将1添加到无符号255时会出现这种情况。 完整的状态标志是CF=1 SF=0 ZF=1 OF=0 AF=1 PF=1,eax为0 但是,第二个操作在设置溢出标志时将127视为有符号整数,如果将127加1,则会发生溢出

    • 我正在设计一个简单的玩具指令集和附带的仿真器,并试图找出支持什么指令。在算术方面,我目前有无符号加法、减法、乘法和除法。然而,对于以下问题,我似乎找不到一个明确的答案:哪种算术运算符需要有符号版本,而无符号和二的补码有符号版本对哪一种是等价的? 例如,1111在2的补码中等于-1。如果你给它加1,假装它是一个无符号的数字,你会得到0000,即使把它想象成-1也是正确的。然而,这适用于所有数字吗?其

    • C语言有符号和无符号类型,如char和int。我不确定它是如何在程序集级别实现的,例如,在我看来,有符号和无符号的乘法会带来不同的结果,那么程序集是同时做无符号和有符号的算术,还是只做一个,这在某种程度上是针对不同情况模拟的?

    • 本文向大家介绍C语言中无符号数和有符号数之间的运算,包括了C语言中无符号数和有符号数之间的运算的使用技巧和注意事项,需要的朋友参考一下 C语言中有符号数和无符号数进行运算(包括逻辑运算和算术运算)默认会将有符号数看成无符号数进行运算,其中算术运算默认返回无符号数,逻辑运算当然是返回0或1了。 unsigned int和int进行运算 直接看例子来说明问题吧 输出结果为: 这是因为a和b进行比较的时

    • 有符号和无符号变量在按位运算上有区别吗?< br >例如,在处理无符号数字时:< br> 将得到00000101。 但当处理带符号的数字时会发生什么?

    • 我在读一本教科书,上面写着: 必须注意机器代码如何区分有符号和无符号值。与C不同,它不将数据类型与每个程序值相关联。相反,它在这两种情况下大多使用相同的(汇编)指令,因为许多算术运算对于无符号和二补码算术具有相同的位级行为。 我不明白这意味着什么,有人能给我举个例子吗?