一、二进制简写形式
16进制可以看成是2进制的简写形式
16进制:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,
2进制:0,1
0000=0,0001=1,0010=2,0011=3,0100=4,0101=5,0110=6,0111=7,1000=8,1001=9,1010=A,1011=B,1100=C,1101=D,1110=E,1111=F
以后熟练掌握16进制与2进制的转换
二、数据宽度
就好比计算机中有很多容器,如酒杯、盆、水桶、缸。
酒杯(位)不能装放盆(字节)里,如果连 缸(双字)都装不下的话,计算机就直接丢弃了。
一个位就能存储一个1或0.
一个字节八个位,一个字十六个位,一个双字32个位
数据宽度最少:全是0;最多:全是1
PS:四个1就是两个FF
1FF存储的时候只能存储FF,而1就被丢弃了
三、有符号数无符号数
无符号数的编码规则就是2进制转换为16进制
有符号数的编码规则是:
最高位是0时,是正数,此时的编码规则与无符号数的一样
有符号数为正数时的编码规则与无符号数为正数时的编码规则相同
当第一个数为0时,就为正数
第一个数为1时,为负数
下图是四位宽度:
上图就能清楚表示,当超过F后,计算机就直接丢弃装不下的数据,也就是说边界就是F和0之间。(这是无符号数)
有符号数的话就存在正负,那么一个圆分为左右两个部分,右边是正数,左边是负数。
而F就是最大的负数为-1.而8对应二进制为1000,为负数,前面的0-7为正数都是0几几几,则有1开头的都是负数,而负数的边界就是F,正数的边界就是7(这是在有符号数的情况下)
那么:-1,-2,-3,-4,-5,-6,-7,-8
F,E, D, C, B, A ,9, 8 一一对应。
边界一被超过,计算机就会扔掉超过边界的值,有符号数无符号数是由个人自己定夺的!
四、逻辑运算
1、或(or ||),只有一个为1就是1,两个1也是1.
2、与(and &),两个都为1才是1.
3、异或(xor ^)不一样为1.
4、非(not !)1是0,0是1.
①如何使用cpu计算2+3:
让我们算的话直接
都转化为四位的二进制进行运算加法,0101转化为10进制就是5.
而让计算机去计算的话,首先定义四个容器a,b,c,d(四个容器都是四位宽度的二进制)之后使用异或计算a(0010)+b(0011)=c(0001)
计算机需要继续计算,使用或计算a(0010)+b(0011)=d(0010),此时的d需要进行左移判断是否为0000,是则c为最终答案,反之,需要令a=c,b=左移后的d。
计算的终点是:计算后的数据左移变为0000.
所以继续异或计算a(0001)+b(0100)=c(0101)
然后或计算a(0001)+b(0100)=d(0000),最后d左移后为0000,则此时的c为最终答案
0101转化为十进制是5。
②如何获得某个值的第N位的值:
例如:用与计算8F(10001111)和00001000,就能得出第四位的值。
③最简单的加密算法:
原理是异或一个数的得数再次异或同一个数,值不变
比如:
要对一个数进行加密,首先需要密钥对其进行异或运算,之后的得数就是加密结果。而接受加密结果的人,只需用密钥对加密结果再来一次异或运算就能得到加密前的数据。
五、寄存器
有32位16位8位的寄存器是根据所要保存的数据不同而定的。就比如一两白酒一个瓶子(8位)而我却要用盆(16位)去装,这是对空间的浪费。
熟记32位16位8位寄存器
语句:
1、
mov:操作码 eax:目标操作数 0xaaaa:原操作数
mov指令的目的就是把原操作数复制一份放到目标操作数里去
mov指令使数据在寄存器之间,寄存器与内存之间移动,而数据移动的越复杂,程序就越复杂,如果弄懂数据的流动,那么对程序就有了初步的理解(逆向就是分析数据怎么跑的)
通过mov指令,我们可以分析eax、ax、ah、al之间的关系
我们先将eax八个位占满
由上面图可以分析得:ax是eax的低位,ah是ax的高位,al是ax的低位
也就是说eax的后一半是ax,ah是ax的前一半,al是ax的后一半。
我们在用mov指令时要确定目标操作数的大小和原操作数的大小一致。
我们用下面这个指令,可以让eax里的内容复制并转移到ecx里
那么同理,可以让ax的内容转移给cx,以此类推
以上是寄存器到寄存器的转移。
2、add语句(加法)
例如:add eax,2
原本在eax里的值是1,然后加2得出的值再储存到eax里
3、sub语句(减法)
例如:sub eax,2
使eax里的值减去2后再储存到eax里
3、and指令(与运算)
eax里储存的是2
经过and运算结果还是2,我们用二进制为:10
and 11
结果为: 10
4、or指令(或运算)
eax里是2,和3进行或运算,结果为3,同理也是运用二进制算法
5、xor指令(异或运算)
6、not指令(非运算)
六、内存
相同点就是:都有定宽,都有边界。
内存的数量特别多,,无法为每个内存都起名字,所以用编号代替。每一块内存都有一个编号。
内存中的每一个字节会有一个编号(内存的编号是内存)
32位计算机的最大编号是32位,也就是32个1,换成16进制就是8个F,也就是32位计算机内存寻址的最大范围是内存的单位,就是字节,而内存中存储的信息最多为:FFFFFFFF+1.
计算一下:FFFFFFFF+1=100000000(转为十进制=4294967296)而1024指的是十进制的,所以要转换为十进制。4294967296/1024=4194304K,4194304/1024=4096MB,4096/1024=4GB
这就是为什么说32位的计算机能识别的内存为4GB,但因为硬件本身会固定的占用内存,cpu也就找不到那些内存了,所以最大内存是小于4GB的。
32位的,64位的计算机跟寄存器宽度没有关系,是跟寻址宽度有关系的(也就是能查找的内存编号,也就是内存的字节的范围)
而32位的计算机能识别的最大内存不一定是4GB,因为可以通过打补丁始使得寻址宽度变大
往内存中写入/读写数据须知:使用内存编号需要用到 “[]”,比如mov [0x12345678],0xffff
但是内存很大,不像寄存器,一旦超过范围寄存器就会自动舍弃左边第一个数,而内存的话会继续存储,所以我们需要指定储存几位的数据:mov word ptr DS:[0x12345678],0xFFFF。
其中word表示存储16位,ptr表示地址,DS:固定写法。
这样表示向内存编号为0x12345678的一块内存中存储0xffff数据
用dtdbug打开一个exe程序,每个exe程序都是有独立的4GB空间,只有这个程序自己用,但其实是假的。所以我们往exe文件中的内存写入数据时地址不能乱写。
下图中都是内存:
我们向这块内存写入数据:
每四个字节命名一块内存
读取内存:因为内存不能读取内存,所以我们需要用到寄存器。
mov eax,dword ptr ds:[0xd6e4d4]: