C编译器如何处理无符号和有符号整数?为什么无符号和有符号算术运算的汇编代码相同? [英] how does c compiler handle unsigned and signed integer? Why the assembly code for unsigned and signed arithmetic operation are the same?

查看:110
本文介绍了C编译器如何处理无符号和有符号整数?为什么无符号和有符号算术运算的汇编代码相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读这本书:CS-APPe2. C具有无符号和带符号的int类型,并且在大多数体系结构中使用二进制补码算法来实现带符号的值;但是在学习了一些汇编代码之后,我发现很少有指令可以区分未签名和已签名.所以我的问题是:

I am reading the book: CS-APPe2. C has unsigned and signed int type and in most architectures uses two's-complement arithmetic to implement signed value; but after learning some assembly code, I found that very few instructions distinguish between unsigned and signed. So my question are:

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

  1. Is it the compiler's responsibility to differentiate signed and unsigned? If yes, how does it do that?

谁实现了二进制补码算法-CPU还是编译器?

Who implements the two's-complement arithmetic - the CPU or the complier?

添加更多信息:

在学习了更多指令之后,实际上其中有些指令可以区分有符号和无符号,例如setg,seta等.此外,CF和OF分别适用于unsigned和.但是大多数整数算术指令都将无符号的和有符号的对待,例如

After learning some more instructions, actually there are some of them differentiate between signed and unsigned, such as setg,seta,etc. Further, CF and OF apply to unsigned and respectively. But most integer arithmetic instructions treat unsigned and signed the same,e.g.

int s = a + b

unsigned s = a + b

生成相同的指令.

因此,在执行ADD s d时,CPU应该将s& d视为未签名还是已签名?还是不相关,因为两个结果的位模式都相同,并且编译器的任务是将基础位模式结果转换为无符号或有符号?

So when executing ADD s d, should the CPU treat s&d unsigned or signed? Or it is irrelevant, because the bit pattern of both result are the same and it is the compiler's task to convert the underlying bit pattern result to unsigned or signed?

P.S我正在使用x86和gcc

P.S i am using x86 and gcc

推荐答案

这很容易.加法和减法之类的运算不需要对二进制补码算术中的有符号类型进行任何调整.只需进行一次思维实验,并想象仅使用以下数学运算即可得出的算法:

It's quite easy. Operations like addition and subtraction don't need any adjustment for signed types in two's complement arithmetic. Just perform a mind experiment and imagine an algorithm using just the following mathematical operations:

  • 增加一分
  • 减一
  • 与零比较

加法只是从一个堆中一个接一个地取出项目,然后将它们放到另一个堆中,直到第一个为空.减法是同时从它们两个中减去,直到被减掉的一个为空.在模块化算术中,您只需将最小值当作最大值加1即可使用.二进制补码只是模运算,最小值为负.

Addition is just taking items one by one from one heap and putting them to the other heap until the first one is empty. Subtraction is taking from both of them at once, until the subtracted one is empty. In modular arithmetics, you just just treat the smallest value as the largest value plus one and it works. Two's complement is just a modular arithmetic where the smallest value is negative.

如果您希望看到任何区别,建议您尝试对溢出不安全的操作.一个例子是比较(a < b).

If you want to see any difference, I recommend you to try operations that aren't safe with respect to overflow. One example is comparison (a < b).

区分签名和签名是编辑者的责任吗 未签名?如果是,它是如何做到的?

Is it the complier's responsibility to differentiate signed and unsigned? If yes, how does it do that?

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

By generating different assembly whenever needed.

谁实现了二进制补码算法-CPU还是编译器?

Who implements the two's-complement arithmetic - the CPU or the complier?

这是一个困难的问题.二进制补码可能是在计算机中使用负整数的最自然的方法.带溢出的二进制补码的大多数运算与带溢出的无符号整数的大多数运算相同.可以从单个位中提取符号.比较可以在概念上通过减法(与符号无关),符号位提取以及与零的比较来完成.

It's a difficult question. Two's complement is probably the most natural way to work with negative integers in a computer. Most operations for two's complement with overflow are the same as for unsigned integers with overflow. The sign can be extracted from a single bit. Comparison can be conceptually done by subtraction (which is signedness-agnostic), sign bit extraction and comparison to zero.

不过,正是CPU的算术功能允许编译器以二进制补码形式生成计算.

It's the CPU's arithmetic features that allow the compiler to produce computations in two's complement, though.

无符号s = a + b

unsigned s = a + b

请注意,此处计算加号的方式不取决于结果的类型. Insead取决于等号右边的变量的类型.

Note that the way plus is computed here don't depend on the result's type. Insead it depends on the types of variables to the right of the equal sign.

因此,在执行ADD s d时,CPU应该将s& d视为未签名还是已签名?

So when executing ADD s d, should the CPU treat s&d unsigned or signed?

CPU指令不知道类型,它们仅由编译器使用.同样,在添加两个无符号数字和添加两个带符号数字之间也没有区别.对于同一操作有两条指令会很愚蠢.

CPU instructions don't know about the types, those are only used by the compiler. Also, there's no difference between adding two unsigned numbers and adding two signed numbers. It would be stupid to have two instructions for the same operation.

这篇关于C编译器如何处理无符号和有符号整数?为什么无符号和有符号算术运算的汇编代码相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆