
汇编
文章平均质量分 84
寻梦&之璐
这个作者很懒,什么都没留下…
展开
-
位运算符实现加法和乘法
文章目录加法:加法:加法:#include <iostream>using namespace std;int main(){ int x, y; cin >> x >> y; int z = x ^ y; int d = x & y; int ands; if (d) { while (d) { int end = (d << 1); ands = (end ^ z); d = (end & z)原创 2021-10-04 17:43:55 · 227 阅读 · 0 评论 -
汇编层探索与讨论c++引用
文章目录提出问题下面提到词汇前提声明第一组:第二组:第三组:第四组:第五组:结论:第七组:第八组:第九组:引用比指针安全????常量引用提出问题定义一个引用类型和将一个变量转换成引用类型一样吗?引用比指针安全,真的是这样吗?对引用不理解的话比指针还危险。为什么要用常量引用传参,只是为了只读?下面提到词汇前提声明对象:不是OO里面的对象,而是泛指在c++语言中某种类型(内嵌,结构体,类)的实例,与变量相同的意思存储体:对象(或变量)的存储内容的控件,一般是内存下面用到的变量命名规则:引用:以原创 2021-02-28 20:58:10 · 1389 阅读 · 0 评论 -
PE结构&整体叙述
PE文件中的对齐数据在内存中的对齐由于Windows操作系统对内存属性结构的设置以页为单位,所以通常情况下,节在内存中的对齐单位必须至少是一个页的大小。对32位的Windows XP操作系统来说,这个值是4KB(1000h);而对于64位操作系统来说,这个值就是8KB(2000h)。数据在文件中的对齐为了提高磁盘利用率,通常情况下,定义的节在文件中的对齐单位要远小于内存对齐单位;通常会以一个物理扇区的大小作为对齐粒度的值,即512字节,十六进制是200h处于节约资源考虑,操作系统允许节在内存和文件原创 2021-01-31 23:17:27 · 6761 阅读 · 5 评论 -
OD软件断点原理
软件断点即int 3----l调试器利用EXCEPTION_BREAKPOINT异常实现断点功能。int 3设置断点命令对应的汇编指令为INT3,对应的机器指令的也就是0xCC。CPU运行代码的过程中若遇到汇编指令INT3,则会触发EXCEPTION_BREAKPOINT异常。在OllyDbg调试器某个地址设置断点后,确定该地址处的指令是否真会变为INT3(0xCC)?OD接下来我们查看以下数据窗口,查看到设置断点的地方,该地址处的指令并未变成INT3(汇编指令),也并未"6A“变成”CC"(原创 2021-01-24 12:29:21 · 4693 阅读 · 0 评论 -
ARM多寄存器加载/存储指令
ARM中如何实现跳转?a. 直接向PC 寄存器赋值实现跳转MOV PC ,R14** b.使用分支指令直接跳转**分支指令种类1.B:分支指令2.BL:带链接的分支指令(可返回)3.BX:带状态切换的分支指令多寄存器加载/存取指令:可以实现在一组寄存器和一块连续的内存但愿之间传输数据LDM 加载多个寄存器STM 存储多个寄存器(允许1条指令传送16个寄存器的任何子集或所有寄存器,主要用于现场保护.数据复制.常数传递等)详情举例:装载指令:LDM 源地址,目标寄存器列表(从原创 2021-01-03 19:22:12 · 1783 阅读 · 0 评论 -
常用ARM指令总结(未完待续)
ARM指令集介绍7种工作模式,2种工作状态ARM指令的种类,共有7类指令,可以完成存储器访问,数据运算,程序跳转,处理器控制,以及帮助编程的伪指令等。数据处理指令大致分为三类:a.数据传送指令b.算数逻辑运算指令c.比较指令数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作。所有的ARM数据处理指令均可以选择使用S后缀,并影响状态标志。数据传送指令MOV 指令可将8位图立即数或寄存器传送到目标寄存器,可用移位运算等操作同类型的指令还有MVN,它可以实现数据的 非传递 ,原创 2020-12-23 15:12:10 · 1142 阅读 · 0 评论 -
ARM处理器寻址方式 之 堆栈寻址
首先呢,得说明一下 满堆栈 和 空堆栈的寻址区别满递增:堆栈向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA,STMFA等空递增:堆栈向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA,STMEA等满递减:堆栈向下增长,堆栈指针指向内含有效数据的最低地址。指令如LDMFD,STMFD等空递减:堆栈向下增长,堆栈指针指向堆栈下的第一个空位置。指令如LDMED,STMED等...原创 2020-12-22 23:57:28 · 1223 阅读 · 0 评论 -
详解虚函数的实现过程之菱形继承修罗场(6)
在这里想跟大家一起来探索一下菱形继承的类对象如何来执行构造函数,以及析构函数原创 2020-12-18 15:04:04 · 2377 阅读 · 0 评论 -
详解虚函数的实现过程之菱形继承(5)
大家看到标题,会不会菱形继承的虚表会不会是重复的呢?祖父类的虚表会不会在子类会不会是两份相同呢?那么我们一起来探索一下吧,冲冲冲!!首先我们来分析一下:它一共定义了四个类,分别为CFurniture,CSofa,CBed和CSofaBed。CFurniture为祖父类,从CFurniture类中派生了两个子类:CSofa与CBed,它们在继承时使用了virtual的方式,即虚继承。接下来我们来看看CSofaBed的对象的内存结构图那么这些数据都有什么含义呢?如下所示:看了一下,大概能看懂原创 2020-12-18 14:16:19 · 3778 阅读 · 3 评论 -
详解虚函数的实现过程之虚基类(4)
博客虚函数实现过程3 时提到过虚基类,这里呢,我们来详细讲述一下:当我们在虚函数的声明结尾处添加“=0”,这种虚函数就被称为纯虚函数。它好似一个没有实现只有声明的函数,它的存在就是为了让类具有抽象类的功能,让继承自抽象类的子类都有虚表和虚表指针。使用过程中,利用抽象类指针可以更好地完成多态工作。如下分析:大家想一想,只有声明却没有实现的函数,它的虚表指针指向的函数那是什么玩意?它还是指向一个函数指针吗?这个函数指针指向的地方是哪里呢?会不会是空?里面难不成放了一个null?还是放了一个报错?或者原创 2020-12-18 11:20:03 · 3591 阅读 · 0 评论 -
详解虚函数的实现过程之多重继承(3)
这里大家猜一下,SofaBed会占多少个字节呢?首先我们是不是得猜一下它有几个虚表指针?4* 4(4个int数据)+2*4(两个虚表指针)=24(字节)那我们一起接下来去验证一下为什么会有两个虚表指针呢?冲冲冲!!!是不是感觉很神,对吧?两个虚表指针,它怎么排兵布阵的呀?这得接下来一起看看喽:从上面表格可以看出它所继承的父类中各自有一个指针,查了一下指针指向的地方,分别是0x426198与0x42501C,接下来我们去看看这两个地方所存在的数据:啊这,这两个虚表里面保存了子类的虚函数和...原创 2020-12-18 10:58:57 · 8206 阅读 · 0 评论 -
析构设置为虚函数的原因
为什么要将析构函数定义为虚函数呢?由于可以使用父类指针保存子类对象的首地址,因此当时用父类指针指向子类堆对象时就会出问题。当使用delete释放对象的空间时,如果析构函数没有定义为虚函数,那么编译器就会按指针的类型调用父类的构造函数,从而引发错误。而使用了析构函数后,会访问虚表并调用对象的析构函数。实现过程如下:对于没有派生和继承关系 的类结构,是否将析构函数声明为虚析构函数不会影响到调用的过程,但是在编写析构函数时形成好习惯,无论当前是否有派生或继承关系,都应将析构声明为虚析构函数。...原创 2020-12-18 01:25:22 · 1167 阅读 · 0 评论 -
详解虚函数的实现过程之单继承(2)
从汇编分析一下下面的多态模拟结构利用 父类指针指向子类的特性,可以间接调用各子类中的虚函数。虽然指针类型为父类,但由于虚表的排列顺序是按虚函数在类继承层次中首次声明的顺序依次排列的,因此,只要继承了父类,其派生类的虚表中的父类部分的排列就与父类的一致,子类新定义的虚函数将会按照声明顺序紧跟其后。我们给Speak函数传递任何一个基于CPerson的派生对象地址都能正确调用虚函数ShowSpeak,那么当我们调用虚函数时,它是如何实现调用的呢?请看下面分析分析如下:地址401108的eax是t原创 2020-12-18 01:17:04 · 8274 阅读 · 1 评论 -
定义派生类和继承类(从汇编分析)
下面我来分析几段继承的类跟大家总结一下前面所说的一些理论知识,这里解释了前面 提供默认构造函数的第二点哦,仔细看仔细观察地址401090,这里先调用了子类的构造函数,但是原来子类里面并没有构造函数,这就是编译器给出的默认构造函数,需要通过这个构造函数,像一个踏板一样,跳到父类的构造函数去,这里就是前面所讲过的 提供默认构造函数的第二点知识。(情况是:父类有构造函数,但是子类没有)(这里我一直在想,不是得先调用父类的构造函数吗,为什么这里先子类呢?因为你要发现是否有父类,你得先进入子类构造函数原创 2020-12-17 23:56:08 · 451 阅读 · 0 评论 -
详解虚函数的实现过程之初探虚表(1)
空对象它有一字节的大小,在没有任何成员变量但是却有虚函数的对象里,它的大小是四个字节,这是为什么呢?因为含有虚函数的对象里,对象的起始地址往后四个字节其实是 一个指针,它指向了一个数组,这个数组的元素是 指针,这些数组的元素指向的地方就是虚函数实现的地方,我们称这个数组叫做 虚表。而指向这个虚表的指针我们成为 虚表指针。这个对象为什么是4个字节的大小,也就是含有这个虚表指针。对于开发者而言,虚表指针都是隐藏的,在常规的开发过程中,我们感受不到它们的存在,要想感知它们的存在,看看底层的汇编代码即可,或者原创 2020-12-17 21:51:56 · 8230 阅读 · 5 评论 -
2020-12-18(何种情况下编译器会提供默认构造函数)
当问到大家什么时候会提供默认构造函数时,有的人会不会一下子就想到当我们没有定义构造函数的时候,它就会提供默认的构造函数,但我们想想一个问题,假如没有意义的情况下提供了默认构造函数,那是不是把编译器搞得像一个傻子一样?所以总结如下:下面两种情况下,编译器才会提供默认的构造函数:a.本类.本类中定义的成员对象或者父类中有虚函数存在解释:由于需要初始化虚表,且这个工作理应在构造函数隐式完成,因此在没有定义构造函数的情况下,编译器会添加默认的构造函数用于隐式完成虚表的创建工作b.父类或本类中定义的成员对象原创 2020-12-17 16:22:25 · 11445 阅读 · 0 评论 -
2020-12-16(虚析构函数,神逻辑代码)
下面这串代码从汇编角度分析的话,大家等几天,我看看,我目前只能从c++层面来解释#include<iostream>#include<stdio.h>using namespace std;class CPerson {public: virtual const char* GetClassName() { return "CPerson"; }virtual void showspeak() { printf("%s::showspeak()\r\n",原创 2020-12-16 23:49:28 · 215 阅读 · 0 评论 -
返回对象2(调用了拷贝构造函数)
触发拷贝构造函数原型 CMyString MyString=GetMystring();这里比较难理解的是,地址401160~地址401164的代码,它把传进来的返回对象this指针和局部对象的首地址当做参数传入了拷贝构造函数,返回对象的this指针的意思就是:当我们要调用一个类的成员函数时,我们必须传入this指针,意思就是告诉函数是哪一个对象调用了它,操作了它。 这里中间插入拷贝构造函数代码助于大家理解而传入局部对象首地址也就是把它当参数传给拷贝构造函数的形参,让函数去拷贝局部对象的一系列的原创 2020-12-15 15:40:03 · 2141 阅读 · 0 评论 -
返回对象1(未调用拷贝构造函数)
对象作为返回值与对象作为参数处理方法非常类似,对象作为参数时,进入函数前预先将对象使用的栈空间保留出来,并将实参对象中的数据复制到栈空间保留出来,并将实参对象中的数据复制到栈空间中。该栈空间作为函数参数,用于函数内部使用。同理对象作为返回值时,进入函数后将申请返回对象使用的栈空间,在退出函数时,将返回对象中的数据复制到临时的栈空间中,以这个临时栈空间的首地址作为返回值。这里我主要把那个 返回对象 临时对象 对象objA 圈了起来,因为这里有个赋值(拷贝)流程(这里的拷贝并未调用到拷贝构造原创 2020-12-15 15:39:55 · 2125 阅读 · 0 评论 -
对象作为函数参数
对象作为函数的参数时,其传递过程较为复杂,传递方式比较独特。其传参过程与数组不同:数组变量的名称代表数组的首地址,而对象的变量名称却不能代表对象的首地址。传参时不会像数组那样以首地址作为函数的参数传递,而是先将对象中的所有数据进行备份(复制),将复制的数据作为形参传递到调用函数中去、类对象中的数据成员的传参顺序为:最先定义的数据成员最后压栈,最后定义的数据成员最先压栈但是当对象里面 申请堆空间的时候,使用 传参且浅拷贝,它只把堆空间地址传过去,拷贝到形参中去,我们从地址40122C可以看出mo原创 2020-12-15 09:31:01 · 2744 阅读 · 0 评论 -
c++对象长度之静态数据成员(3)
当类中定义了静态数据成员。当类中定义了静态数据成员时,由于静态数据成员静态变量原理相同(是一个含有作用域的特殊全局变量),因此该静态数据成员的初值会被写入编译链接后的执行文件中。当程序被加载时,操作系统将执行文件中的数据读到对应的内存单元里,静态数据和曾元便已经存在,而这时类并没有实例对象。所以静态数据成员和对象之间的生命周期不同,并且静态数据成员也不属于某一对象,与对象之间是一对多的关系。因为静态数组成员有此特性,所以在计算类和对象的长度时,静态数据成员属于特殊的独立个体,不被计算在其中。如以下代码原创 2020-12-14 16:45:03 · 286 阅读 · 0 评论 -
c++对象长度之内存对齐(2)
内存对齐在VC++6.0中,类和结构体中的数据成员是根据它们在类或结构体中出现的顺序来依次申请申请内存空间的,由于内存对齐的原因,它们并不一定会像数组那样连续地排列。由于数据类型的不同,因此占用的内存空间大小也会不同,因此占用的内存空间大小也会不同,在申请内存时,会遵守一定的规则。要找对齐的话,我个人感觉应该先找到编译器的指定对齐值,因为结构体中的当前数据成员类型长度为M,指定的对齐值是N,那么实际的对齐值为q=min(M,N),其成员的地址安排在q的倍数上。但是,并非设定了默认对齐值就将结构体的对原创 2020-12-14 15:41:13 · 2295 阅读 · 1 评论 -
2020-12-14(全局/静态对象的构造函数和析构函数调用的时机以及地址)
一般的对象实例化在什么时候实例化的呢?是不是在main函数运行到那里的时候,然后创建对象,会调用类里面的构造函数。那当我们遇到全局/静态对象的时候,它是不是也是需要在main函数里面慢慢构造呢?答案是 :不是的。全局/静态对象 的构造函数调用实在main函数之前的。有人在疑问?main函数之前还有函数?不是从main函数开始运行的吗?当然不是啦,明天揭晓这个秘密,今晚复习离散...原创 2020-12-13 21:09:53 · 1682 阅读 · 5 评论 -
c++对象长度之空类(1)
在c++中说起对象,大家是不是很熟悉?对象嘛,new一个不就行了嘛,对吧?(这里不说malloc,malloc它不负责触发构造函数,它也不是运算符,没法重载)但当我们提到对象大小的时候,大家对怎么计算呢?是不是直接:对象长度=sizeof(数据成员1)+sizeof(数据成员2)+sizeof(数据成员3)+sizeof(数据成员4)+…………sizeof(数据成员n)是这样对嘛?那我们用这个公式验证一下空对象的大小是不是应该为0呢?对吧?那我们来验证一下哎呀,怎么不为0呢?详情我明天揭晓,原创 2020-12-13 20:58:04 · 440 阅读 · 0 评论 -
2020-12-12(c++多维数组的反编译观察)
c++一维数组的话,大家都知道,就把数组内容存放在相应的内存地址所对应的地址单元中,举个例子:nArray[4]={1,2,3,4}存储如下:但c++二维数组存储方式大家想过有什么不同的吗?nArray[2][2]={1,2,3,4}存储如下其实大家看了之后,是不是感觉都一样呀。。。唉,其实呢,就不存在什么二维数组,三维数组,四维数组什么的,都是线性存储。总结一句话来说,也就是(二维数组是由n个一维数组构成,三维数组是由n个二维数组构成,四维数组是由n个三维数组构成……)以此类推,只不过呢,他们各自原创 2020-12-12 15:54:51 · 3792 阅读 · 1 评论 -
DMB DSB ISB 简介
DMB: Data memory barrier理解DMB指令,先看下面例子,在core 0和core1上同时跑两个不同的指令(如下表所示)core 0core 1Write A;Load B;Write B;Load B;这里core0在执行两个指令,写A B两个值的时候,可能会发生乱序也可能Write A时发生Cache Miss,那么就会导致在cache中 A的最新值更新慢于B的最新值。于是在core1中的指令Load B就会拿到新值,而Load A 就会拿到旧转载 2020-12-11 01:09:35 · 1319 阅读 · 0 评论 -
2020-12-7(字节,半字,字,双字总结)
一、对于嵌入式底层开发人员字(Word):在ARM体系结构中,字的长度为32位,而在8位/16位处理器体系结构中,字的长度一般为16位。半字(Half-Word):在ARM体系结构中,半字的长度为16位,与8位/16位处理器体系结构中字的长度一致。字节(Byte):在ARM体系结构和8位/16位处理器体系结构中,字节的长度均为8位。ARM 采用的是32位架构.ARM约定:Byte : 8 bitsHalfword :16 bits (2 byte)Word : 32 bits (4 byte原创 2020-12-11 01:03:46 · 2193 阅读 · 5 评论 -
ARM平台下独占访问指令LDREX和STREX的原理与使用详解
为了实现线程间同步,一般都要在执行关键代码段之前加互斥(Mutex)锁,且在执行完关键代码段之后解锁。为了实现所谓的互斥锁的概念,一般都需要所在平台提供支持。在计算机领域里,如果要在多线程的情况下要保持数据的同步,需要引入称作Load-Link(LL)和Store-Conditional(SC)的操作,通常简称为LL/SC。LL操作返回一个内存地址上当前存储的值,后面的SC操作,会向这个内存地址写入一个新值,但是只有在这个内存地址上存储的值,从上个LL操作开始直到现在都没有发生改变的情况下,写入操作才能成转载 2020-12-11 01:01:46 · 828 阅读 · 0 评论 -
2020-12-6(从反汇编理解指针和引用的区别)
这是我10个月前看到的一篇博客吧,感觉分析指针和引用的文章这是我目前见过讲解得最清晰的一篇:本文主要基于反汇编代码,从初始化、赋值以及取地址三个角度来理解指针和引用的区别。初始化写出以下代码并查看反汇编代码:int main(){ int x = 5; int * ptr = &x; //指针 int & ref = x; //引用 return 0;}在初始化阶段,指针和引用的行为都是一样的:先将x的地址加载到寄存器eax中,转载 2020-12-10 12:39:01 · 497 阅读 · 1 评论 -
2020-12-4((ARM汇编)mov指令,LDR指令,LDR伪指令)
首先说明一下 ARM是RISC(“reduced instruction set computer”,即“精简指令集计算机”)结构x86是CISC(“Complex Instruction Set Computer”,即“复杂指令系统计算机”)结构想表达个什么意思呢?也就是它俩不一样,至于怎么不一样呢,并非这篇博客讨论的要点。因此mov指令使用起来也不一样。接下来介绍一下ARM里面的mov指令mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地原创 2020-12-05 20:20:32 · 2650 阅读 · 1 评论 -
2020-12-2(详细解释neg指令 以及SCAS ,STOS的运用)
neg指令(求补) 也就是前面我们所提到过的补码的非这个neg指令可以配合标志寄存器里面的CF位和OF位使用a.不为0的操作数求补 CF=1b.为0的操作数求补 CF=0c.操作数为-128(字节运算)或操作数为-32768(字运算) OF=1d.当求补运算的操作数不为-128(字节)或操作数为-32768(字运算) OF=0利用这个可以实现条件跳转SCAS 隐式地把AL/AX/EAX的数值与地址为EDI的内存数值比较(可以实现C语言里面的strlen函数)xor al,al原创 2020-12-02 23:23:55 · 9318 阅读 · 0 评论 -
2020-11-29(准备考试)
今天复习了一天的课本知识,准确滴说是预习。。。。。唉,懂的都懂,博客今天就随便发点,明天我们继续开启刷博客的道路。原创 2020-11-29 23:52:26 · 213 阅读 · 0 评论 -
2020-11-28(不定参数的函数)
c\c++将不定长参数的函数定义为:a.至少要有一个参数;b.所有不定长的参数类型传入时都是dword类型;c.需在某一个参数中描述参数的总个数或将最后一个参数赋值为结尾标记。有了这三个特性,就可以是实现不定参数的函数。(printf函数就是利用第一个参数来获取参数总个数的,只需要检查printf函数中第一个参数指向的字符串中包含几个“%”就可以确定其后的参数个数(“%%”形成的转义字符除外))根据参数的传递特性,只要确定第一个参数的地址,对其地址值做加法,就可访问到此参数的下一个参数所在的地址。原创 2020-11-28 22:47:39 · 3825 阅读 · 0 评论 -
2020-11-28(全局变量和局部静态变量)
常量和全局变量有着相似的特征,都是在程序执行前就存在了。在大多数情况下,在PE文件中的只读数据节中常量的节属性被修饰为不可写;而全局变量和静态变量则在属性为可读写的数据节中。具有初始值的全局变量,其值初始值的全局变量,其值在链接时被写入所创建的PE文件中,诞生于所在执行文件被操作系统加载后,执行第一行代码前,这个时候就已经具有内存地址了。在访问方式上,局部变量的访问时通过栈指针相对间接访问,而全局变量的内存地址在全局数据区,通过栈指针无法访问到 ,但 由于全局变量在编译期就已经确定了具体的地址,因此编原创 2020-11-28 22:32:17 · 375 阅读 · 0 评论 -
2020-11-27(switch的优化问题)
第一次看switch的case表的时候,那是半年前了,看完了有序线性然后去看非线性索引时,实在看不下去了,今天再一次拿出这本书,把switch 的 有序线性 ,非线性,以及 判断树 看了一遍,感触挺深的吧,接下来让我们一起被switch虐吧。1.首先,二话不说,上代码,代码具有较高说服力两份代码debug版本相比较后,大家可以发现,if……else if 结构会在条件跳转后紧跟语句块;而switch结构则将所有条件跳转都放置到了一起,并没有发现case语句的踪影。通过条件跳转指令,跳转到相应的ca原创 2020-11-27 23:04:06 · 20308 阅读 · 7 评论 -
2020-11-27(下标寻址和指针寻址)
访问数组的方法有两种:通过下标访问和通过指针访问指针寻址的方式不但没有下标寻址方式遍历,而且效率也比下标寻址寻址低。a.由于指针是存放地址数据的变量类型,因此在数据访问的过程中需要先取出指针变量中的数据,然后再针对此数据进行地址偏移计算,从而寻址到目标数据。b.但数组名本身就是常量地址,可直接针对数组名所替代的地址值进行偏移计算。char * pchar=NULL;char szbuff[]="Hello";pchar=szbuff;printf("%c",*pchar)mov eax,d原创 2020-11-27 20:44:45 · 771 阅读 · 0 评论 -
2020-10-27(原码,反码,补码的产生)
补码诞生的背景不论是在生活中还是虚拟网络中,人们总是习惯与10进制数字打交道,很容易理解10进制的加减乘除运算,但是我们知道计算机无法直接理解10进制,只能识别高低电平,一般人为设定0为低电平,1为高电平,所以又称计算机是二进制的。在计算机发展早期,人们要想使用计算机,只能使用计算机看懂的二进制与计算机打交道,如穿孔纸带,人们使用穿孔纸带将程序和数据转换为二进制码,带孔为1,无孔为0,计算机读取并处理完成后,同样在纸带上以二进制打孔输出计算结果,一般人很难操作这种早期计算机,只能是专业人士才能处理二进..转载 2020-10-27 22:53:49 · 1335 阅读 · 0 评论 -
2020-10-27(补码10000000为什么可以表示-128?)
一、引言本文转自知乎上 fhylhl 用户对于此同名问题的解答,本人觉得回答得非常鞭辟入里,因此咨询了作者是否可以转载,得到了肯定的回复后才进行了转载。另外,什么是补码?补码的设计意义是什么?让我们忘记公式,来看看作者的回答。二、正文很多人并不理解补码。补码就是同余啊。1000000是正128你知道吧,正负128模256是同余的。加减乘可以直接算也是同余的定理决定的,而不是凑出来的巧合,哪可能凑出这种东西?8位只能表示256个数,0到255,但我还想表示一些负数怎么办呢?就用与该负数同余的正数来转载 2020-10-27 22:35:21 · 898 阅读 · 1 评论 -
2020-10-27(汇编收获)
3.从汇编角度以及内存角度去理解虚函数的调用,利用了虚表4.null就是一个宏定义 #define null 0 表示整型nullptr专门表示指针为空,既05.编译模板所在的源文件时,没有发现任何人使用此模板,是不会生成相应的函数实现的!所以模板放在头文件里面,不会放声明和实现分开来放,一般放在hpp中!编译时把每个cpp源文件分开编译成obj文件,链接时来纠正main函数里面call的地址!(既模板未被使用时,不会被实例化出来,也就不会生成相应的函数代码)所以模板的声明和实现如何分离到头文件和原创 2020-10-27 09:17:13 · 3678 阅读 · 0 评论 -
2020-11-15(IEEE浮点数计算)
V=2^E*M(符号位另算)eg:0 0110 . 0100s E Mf是小数位真正的值(不分规格化和规格化)规格化数E=e-(2^ (k-1) -1)=6-(2^(4-1)-1)=6-7=-1e=6k=4M=1+f非规格化数 eg: 0 1111 0100 | 0 0000 0100M=fE=1-(2^(k-1)-1)E全为0时,只用计算尾数M就行NaN不是一个数,浮点数对比时,查看PF,如果为1,则其中有一个浮点数为NaN,则此比较恒为032原创 2020-11-15 10:29:02 · 340 阅读 · 0 评论