Tan's Blog.

CSAPP整数的运算

字数统计: 1.3k阅读时长: 4 min
2019/05/07 Share

计算机系统学习

整数的运算

平时的编程过程中,当进行整数运算时,经常会遇到一些奇怪的结果,比如两个正数加出负数,两个负数可以加出一个正数,这些都是由于数值表示的有限性导致的。
无符号的加法
二进制整数的加法与我们平时的十进制算法有一个最大的区别,那就是我们在计算机当中进行计算时,结果的位数都是有限制的。因此在我们计算过后,可能需要对结果进行截断操作。如果结果用超出规定的位才能表示,就算是溢出。所以来说无符号的加法只要不溢出就可以按照正常的加法来算,但如果出现溢出就需要减2^w。
补码的加法
对于补码加法就是可以先按照无符号加法进行运算,然后再进行无符号和有符号的转换。
与无符号加法不同的是,补码的加法会出现三种结果,一种是正常的结果,一种是正溢出,一种是负溢出。对于当正溢出的时候,我们的结果与无符号数类似,相加后的结果减去2^w。而当负溢出的时候,则刚好相反,相加后的结果加上2^w。
补码的非
先明白一个概念,对于任意一个w位的补码数t来说,它都有唯一的逆元t^-1,使得t + t^-1 = 0。
一个w位的补码数的范围在-2^(w-1)到2^(w-1)之间,直观的可以看出,对于不等于-2^(w-1)的补码数x来说,它的逆元就是-x。而对于-2^(w-1)来说,它的二进制位表示为1后面跟着w-1个0,我们需要找到一个数与其相加之后结果为0。这种时候我们需要考虑的是,如果是-x,也就是2^(w-1),则它的位表示需要w+1位,是不存在的。因此我们需要考虑溢出的情况,负溢出的时候需要加上2^w,因此-2w-1的逆元就是-2^w + 2^(w-1) = -2^(w-1),也就是它本身。
无符号乘法
无符号的乘法与加法类似,它的运算方式是比较简单的,只是也可能产生溢出。对于两个w位的无符号数来说,它们的乘积范围在0到(2^w-1)^2之间,因此可能需要2w位二进制才能表示。因此由于位数的限制,假设两个w位的无符号数的真实乘积为result,根据截断的规则,则实际得到的乘积为 result mod 2^w。
补码乘法
与加法运算类似,补码乘法也是建立在无符号的基础之上的,因此我们可以很容易的得到,对于两个w位的补码数来说,假设它们的真实乘积为result,则实际得到的乘积为 U2Tw(result mod 2^w)。
乘以常数
对于一个w位的二进制数来说,它与2^k的乘积,等同于这个二进制数左移k位,在低位补k个0。
除以2的幂
1.除以2的幂的无符号除法:对于一个w位的二进制数来说,它除以2^k,等同于这个二进制数右移k位,在高位补k个0。
2.除以2的幂的补码除法:对于一个w位的非负数的二进制数来说,它除以2^k,等同于这个二进制数右移k位,在高位补k个1;而对于一个w位的负数的二进制数来说,它除以2^k,要先加上2^k-1,然后再右移k位,在高位补k个1。

总结

计算机执行整数运算实际上是一种模运算形式,由于数字长度的限制,就会出现溢出的现象,这样就会导致程序运行错误,也会出现许多漏洞,比如在分配地址空间时,发生了正溢出,得到的结果比我们预想的小得多,这样就会导致分配的地址空间变小,而对这些空间进行某些操作时,会破坏超出这些地址空间的数据。

地址传送指令

指令格式名称功能
lea r16,mem有效地址传送指令r16<-mem的有效地址
lds r16,mem指针传送指令r16<-mem,DS<-mem+2
les r16,mem指针传送指令r16<-mem,ES<-mem+2

LEA指令将存储器操作数mem的4位16进制偏移地址送到指定的寄存器。这里,源操作数必须是存储器操作数,目标操作数必须是16位通用寄存器。对于LEA指令来说变量其后面的有无[]皆可,都表示取变量地址,相当于指针;寄存器无[]表示取地址,有[]表示取值。
lds和les的操作过程差不多,r16是一个16位寄存器,mem是一个存储器操作数,为双字项,高16位送入DS/ES,低16位送入r16.

CATALOG
  1. 1. 计算机系统学习
    1. 1.1. 整数的运算
    2. 1.2. 总结
  2. 2. 地址传送指令