Tan's Blog.

CSAPP整数的表示

字数统计: 1k阅读时长: 3 min
2019/05/05 Share

计算机系统学习

今天学习了整数的表示,一般编码整数有两种方式:一种只能表示非负数,而另一种能够表示负数、零和整数。这样就把整数分为无符号数unsigned和有符号数int(默认),通过今天的学习初步掌握了几种编码类型和它们之间的转换。

编码类型

无符号编码
其实无符号编码就是我们平时最直接的读法,没有符号位,直接可以转换位十进制数。对于一个w位的二进制数来说,取值范围是[0,2^w-1]。
补码
无符号编码读起来直接自然,但是可惜的是,它无法表示负整数。因此我们需要一种能够表示负数的整数表示方式,这样就引出了补码编码。补码表示的二进制数,最高位是符号位,0为非负数,1为负数。补码的定义如下

我们观察这个公式,不难看出,补码格式下,对于一个w位的二进制序列来说,当最高位为1,其余位全为0时,得到的就是补码格式的最小值,即TMinw = -2^w-1;而当最高位为0,其余位全为1时,得到的就是补码格式的最大值,即TMaxw = 2^(w-1)-1
反码和原码
有符号数还有两种表示方法:反码和原码
反码和补码的区别在于,除了最高有效位的权是-[2^(w-1)-1]而不是-2^(w-1)],它们没有别的区别。
而原码,最高有效位是符号位,仅用来确定正负,剩下的位是具体的数,按照我们平时的读法来读就可以。

不同编码的转换

在C语言当中,我们经常会使用强制类型转换,而在之前的章节中,也学习过强制类型转换。强制类型转换不会改变二进制序列,但是会改变数据类型的大小以及解释方式,那么考虑相同整数类型的无符号编码和补码编码,数据类型的大小是没有任何变化的,变化的就是它们的解释方式。比如1001这个二进制序列,如果用无符号编码解释的话就是表示9,而若采用补码编码解释的话,则是表示-7。
补码转无符号数
通过分析书上的例子,总结出一条规律就是,假设补码表示的数为x,当x<0时为x+2^w,当x>=0为x。为什么会得出来这样的结果?主要是因为最高位是否为符号位而产生的差异。
无符号数转补码
无符号数转补码同样有规律,同样设无符号数为x,当x<=TMaxw时,为x,当x>TMaxw时,为x-2^w.得出这样的结果原因同上。
C语言中的有符号数和无符号数可以通过隐式转换或者显式转换的方式实现。

堆栈操作指令

指令格式名称功能
push reg/mem/seg进栈指令SP<-SP-2,[sp]<-reg/mem/seg
pop reg/mem/seg出栈指令reg/mem/seg<-[sp],SP<-SP+2

PUSH

PUSH指令即先修改堆栈指针SP(压入时为自动减2),然后将指定的操作数送入新的栈顶位置。push的操作过程可以用下面的代码来表示。

1
2
3
4
5
PUSH:
R[$SP]= R[$SP]-2;
badStack(R[$SP],R[$IP]);
RAM[R[$SP]] = R[RAM[R[$IP]+1]];
R[$IP]=R[$IP]+2;

POP

POP指令和PUSH指令是相对而言的,POP指令是将堆栈段中当前SS:SP所指的字内容弹出到某个寄存器或段寄存器或内存单元,然后再修改堆栈指针SP,指向新的栈顶。POP的操作过程可以用下面的代码来表示。

1
2
3
4
5
POP:
R[RAM[R[$IP]+1]]=RAM[R[$SP]]);
R[$SP]=R[$SP]+2;
badStack(R[$SP],R[$IP]);
R[$IP] = R[$IP]+2;

CATALOG
  1. 1. 计算机系统学习
    1. 1.1. 编码类型
    2. 1.2. 不同编码的转换
  2. 2. 堆栈操作指令
    1. 2.1. PUSH
    2. 2.2. POP