CSAPP(补充)-- C++中正负数的反码操作
创始人
2024-04-01 16:50:33
0

C++ 中的反码计算,要先转补码,结果也要转为相应的补码,这个操作也体现出C++对数字的专一性,它内部实现逻辑的完整性,因为对于计算机中的有符号的数字都是以补码方式存储,代码中列举了有符号的数字反码计算流程

#include 
#include 
#include 
using namespace std;int main(){ios::sync_with_stdio(false);int b = -5;int a = ~b; // -5 --> 100...101// // 找出-5的补码 (c++会把这个数转成补码计算) // 111...011//按位取反// 000...100// 正数的补码是自己,故成立//b = 5//b = 000..101// 补码就是自己,直接按位取反//~b = 111..010 (这个可以看作内存中的结果)//是个负数 取出他的补码 (就是在计算机中存储的方式)// next 100..101 + 1 = 100..110 = -6 (因为我定义的是int, 所以相当于经历了向有符号的转变。//综上所述,为了求得反码,需要分别考虑正数和负数的开端和结果的情况// 都要转为补码进行运算// or 直接根据公式来算 // -a = ~a + 1cout << a << endl;return 0;
}

扩展
对于计算机而言是不需要判断有符号数和无符号数的,都是一样地处理,大概学校里不少老师也都是这么教的,这个话确实是对的,但是得加个限制条件“在硬件层面”,在软件层面并不完全如此,至少在汇编层面还是会区分有符号数和无符号数的。汇编对于有符号数和无符号数的加法指令是通用的,但是乘法和除法指令是有两套的,这个区分是由编译器完成的,高级语言转汇编时会根据变量类型调用不同的汇编函数

show you the code.

在Intel的64位X86CPU上,Windows系统下使用Visual Studio用C语言进行测试。

先看看加法,对于如下的C代码段1,得到转成的汇编代码如汇编代码段1。

//C代码段1
#include
int main() {int a = 12;int b = 20;int c = a + b;
}

转成汇编://汇编代码段1

#include
int main() {
00C21750  push        ebp  
00C21751  mov         ebp,esp  
00C21753  sub         esp,0E4h  
00C21759  push        ebx  
00C2175A  push        esi  
00C2175B  push        edi  
00C2175C  lea         edi,[ebp-0E4h]  
00C21762  mov         ecx,39h  
00C21767  mov         eax,0CCCCCCCCh  
00C2176C  rep stos    dword ptr es:[edi]  
00C2176E  mov         ecx,offset _DC84FF0F_test@c (0C2C003h)  
00C21773  call        @__CheckForDebuggerJustMyCode@4 (0C21307h)  int a = 12;
00C21778  mov         dword ptr [a],0Ch  int b = 20;
00C2177F  mov         dword ptr [b],14h  int c = a + b;
00C21786  mov         eax,dword ptr [a]  
00C21789  add         eax,dword ptr [b]  
00C2178C  mov         dword ptr [c],eax  
}
00C2178F  xor         eax,eax  
00C21791  pop         edi  
00C21792  pop         esi  
00C21793  pop         ebx  
00C21794  add         esp,0E4h  
00C2179A  cmp         ebp,esp  
00C2179C  call        __RTC_CheckEsp (0C21230h)  
00C217A1  mov         esp,ebp  
00C217A3  pop         ebp  
00C217A4  ret 

对于如下的C代码段2,得到转成的汇编代码如汇编代码段2。//C代码段2

#include
int main() {unsigned int a = 12;unsigned int b = 20;unsigned int c = a + b;
}

转成汇编://汇编代码段2

#include
int main() {
007B1750  push        ebp  
007B1751  mov         ebp,esp  
007B1753  sub         esp,0E4h  
007B1759  push        ebx  
007B175A  push        esi  
007B175B  push        edi  
007B175C  lea         edi,[ebp-0E4h]  
007B1762  mov         ecx,39h  
007B1767  mov         eax,0CCCCCCCCh  
007B176C  rep stos    dword ptr es:[edi]  
007B176E  mov         ecx,offset _DC84FF0F_test@c (07BC003h)  
007B1773  call        @__CheckForDebuggerJustMyCode@4 (07B1307h)  unsigned int a = 12;
007B1778  mov         dword ptr [a],0Ch  unsigned int b = 20;
007B177F  mov         dword ptr [b],14h  unsigned int c = a + b;
007B1786  mov         eax,dword ptr [a]  
007B1789  add         eax,dword ptr [b]  
007B178C  mov         dword ptr [c],eax  
}
007B178F  xor         eax,eax  
007B1791  pop         edi  
007B1792  pop         esi  
007B1793  pop         ebx  
007B1794  add         esp,0E4h  
007B179A  cmp         ebp,esp  
007B179C  call        __RTC_CheckEsp (07B1230h)  
007B17A1  mov         esp,ebp  
007B17A3  pop         ebp  
007B17A4  ret

可以看到对于都是正数的整型数相加和无符号整型数相加,他们转成汇编是完全一致的。这也很容易理解,对于整型数12、20和无符号整型数12、20,他们在内存中是完全一致的,相加指令也相同。那么我们考虑下正数和负数相加呢?整型数情况//C代码段3

#include
int main() {int a = -12;int b = 8;int c = a + b;
}

转成汇编://汇编代码段3

#include
int main() {
008C1750  push        ebp  
008C1751  mov         ebp,esp  
008C1753  sub         esp,0E4h  
008C1759  push        ebx  
008C175A  push        esi  
008C175B  push        edi  
008C175C  lea         edi,[ebp-0E4h]  
008C1762  mov         ecx,39h  
008C1767  mov         eax,0CCCCCCCCh  
008C176C  rep stos    dword ptr es:[edi]  
008C176E  mov         ecx,offset _DC84FF0F_test@c (08CC003h)  
008C1773  call        @__CheckForDebuggerJustMyCode@4 (08C1307h)  int a = -12;
008C1778  mov         dword ptr [a],0FFFFFFF4h  int b = 8;
008C177F  mov         dword ptr [b],8  int c = a + b;
008C1786  mov         eax,dword ptr [a]  
008C1789  add         eax,dword ptr [b]  
008C178C  mov         dword ptr [c],eax  
}
008C178F  xor         eax,eax  
008C1791  pop         edi  
008C1792  pop         esi  
008C1793  pop         ebx  
008C1794  add         esp,0E4h  
008C179A  cmp         ebp,esp  
008C179C  call        __RTC_CheckEsp (08C1230h)  
008C17A1  mov         esp,ebp  
008C17A3  pop         ebp  
008C17A4  ret  无符号整型数情况//C代码段4
#include
int main() {unsigned int a = -12;unsigned int b = 8;unsigned int c = a + b;
}

转成汇编://汇编代码段4

#include
int main() {
00D41750  push        ebp  
00D41751  mov         ebp,esp  
00D41753  sub         esp,0E4h  
00D41759  push        ebx  
00D4175A  push        esi  
00D4175B  push        edi  
00D4175C  lea         edi,[ebp-0E4h]  
00D41762  mov         ecx,39h  
00D41767  mov         eax,0CCCCCCCCh  
00D4176C  rep stos    dword ptr es:[edi]  
00D4176E  mov         ecx,offset _DC84FF0F_test@c (0D4C003h)  
00D41773  call        @__CheckForDebuggerJustMyCode@4 (0D41307h)  unsigned int a = -12;
00D41778  mov         dword ptr [a],0FFFFFFF4h  unsigned int b = 8;
00D4177F  mov         dword ptr [b],8  unsigned int c = a + b;
00D41786  mov         eax,dword ptr [a]  
00D41789  add         eax,dword ptr [b]  
00D4178C  mov         dword ptr [c],eax  
}
00D4178F  xor         eax,eax  
00D41791  pop         edi  
00D41792  pop         esi  
00D41793  pop         ebx  
00D41794  add         esp,0E4h  
00D4179A  cmp         ebp,esp  
00D4179C  call        __RTC_CheckEsp (0D41230h)  
00D417A1  mov         esp,ebp  
00D417A3  pop         ebp  
00D417A4  ret 

可以看到这次结果还是完全一样,不管是整型数还是无符号整型数-12都是以补码形式存储在内存中,不过对于无符号整型数来说会把-12当成4294967284。
原码:1000 0000 0000 0000 0000 0000 0000 1100
反码:1111 1111 1111 1111 1111 1111 1111 0011
补码:1111 1111 1111 1111 1111 1111 1111 0100(内存中存储的结果)

8的原码和补码相同8的原码(补码):0000 0000 0000 0000 0000 0000 0000 1000
相加后的结果是:
补码相加:1111 1111 1111 1111 1111 1111 1111 1100(内存中存储的结果)
反码 :1000 0000 0000 0000 0000 0000 0000 0011
反码 :1000 0000 0000 0000 0000 0000 0000 0100这个最终内存中的结果如果视为整型数的补码,结果就是-4;
视作无符号整型数就是4294967292,结果都是正确的,所以计算机对于整型数和无符号整型数的加法是完全一样地处理方法。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...