进制转换、数值与编码

进制转换、数值与编码

x86使用小端方式存储数据

小尾方式(小端方式):

低数位 —> 低地址

高数位 —> 高地址

例如,12345678以小端方式表示为

78 56 34 12

低地址 高地址

2进制转8进制、2进制转16进

2进制 8进制
000 00
001 01
010 02
011 03
100 04
101 05
110 06
111 07
2进制 16进制
0000 0x0
0001 0x1
0010 0x2
0011 0x3
0100 0x4
0101 0x5
0110 0x6
0111 0x7
1000 0x8
1001 0x9
1010 0xA
1011 0xB
1100 0xC
1101 0xD
1110 0xE
1111 0xF

进制本质

以 n 进制的 xyzmk 为例:

x y z m k

指数位:

4 3 2 1 0

n 进制数的计算过程:

xyzmk=xn4+yn3+zn2+mn1+kn0

进制转换

整数

不同进制数的转换,例如十进制转二进制,以123为例:

123/2=611

(个位)

61/2=301

30/2=150

15/2=71

7/2=31

3/2=11

1/2=01

把余数从下往上写,就是1111011

小数

小数二进制和十进制互转,二进制的101.111转为十进制:

122+021+121+12(1)+12(2)+12(3)=4+0+1+0.5+0.25+0.125=5.875

十进制小数转二进制

小数部分x2再取个位,十进制的`0.375“转为二进制:

0.3752=0.75

个位0

0.752=1.5

个位1

0.52=1

个位1 (1.5-1再除以2)

小数需要正着写,就是0.011

十进制0.6转为二进制:

0.62=1.2

个位1

0.22=0.4

个位0

0.42=0.8

个位0

0.82=1.6

个位1

0.62=1.2

个位1

所以,是0.100110011001......

浮点数

定点小数:小数点固定,例如XX.XX

浮点小数:小数点不固定,例如

                          [X][XXX]

                   [小数点位置][数值]

定义一个浮点数:
float f = 3.75f 3.75后面需要加上f或者F来表示是一个单精度浮点数,如果不加,表示double类型,相当于从double类型转为float类型,可能会有精度丢失情况,例如循环小数。

IEEE提供标准,规定了浮点数的编码格式:

float: S EEEEEEEE DDDDDDDDDDDDDDDDDDDDDDD
位数 1 8 23
double: S EEEEEEEEEEE DDDDDDDDDDDDDDD。。。
位数 1 11 52

S表示符号位,0为正数,1为负数;E为指数位,用127表示0(方便用一个正数表示指数的负数形式),D为数据位

练习1:

3.75 float在内存中如何表示?
3.75 转为二进制数为11.11
11.11
=1.111*2^1 //11.11是正数,所以符号位是0,指数位是127+1,小数点前面的1省略掉,剩下的就是数据位
=0 127+1 11100000000000000000000
=0 10000000 11100000000000000000000
=0100 0000 0111 0000 0000 0000 0000 0000 //方便看,每4位分割一下
= 4 0 7 0 0 0 0 0 //转成16进制
=40700000
所以在内存里就是00 00 70 40

练习2:

3.75 double在内存中如何表示?
11.11
=1.111*2^1
=0 1023+1 1110000000000000000000000000000000000000000000000000
=0 10000000000 1110000000000000000000000000000000000000000000000000
=0100 0000 0000 1110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
=4 0 0 0xE 0 0 0 0 0 0 0 0 0 0 0 0
=400E000000000000
所以在内存里表示为 0000000000000E40

补码和求补运算

以一个字节为例:

   S DDDDDDD

 符号位 数据位

S0,表示正数,数据按原数存放;

S1,表示负数,数据求补后存放。(还原时,减1取反和取反加1结果一样)

求补运算:在字长表达范围内,取反加1。

补码和求补运算的区别:

补码,只是一种规则,计算机中,负数以补码形式存放;

求补运算,相当于求负数,正数求负数变负数,负数求负数变正数,求补运算不区分正负。

计算减法过程

a-b,其中ab的范围都是00~FF100h

推导过程如下:

a – b

=a+(100h-b)-100h

其中,b+~b=ffh

所以,b+~b+1=ffh+1=100h

所以,~b+1=100h-b

所以,a-b=a+(~b+1)-100h,其中(~b+1)可以表示为neg(b),neg是汇编指令中的求补指令,neg指令对操作数执行求补运算,-100h可以将进位丢掉。

小结:a-b = a + neg(b),然后舍弃进位。

公式:

neg A = -A (A不等于0)

neg neg A = A (对一个数两次求补其值不变,也就是负负得正)

再以计算 8 – 3 为例

8转为二进制数 0000 1000B

-3 转为二进制数 3取反加1 ——> 0000 0011B 取反变为 1111 1100B 再加1 ——> 1111 1101B

0000 1000B + 1111 1101B = 1 0000 0101B,去掉最高位得 0000 0101B,最后结果为5。

乘法:

a * 54h

=a*1010100B

=a*1000000B + a*10000 + a*100

=a << 6 + a << 4 + a << 2

-128转补码:

最高位是符号位,其余位为数字的原码取反+1
1000 0000还原为原码:
最高位是1,表示负数,剩余的各位取反111 1111+1,得到1000 0000, +128的原码,整个数为-128,其实就是0。

常用缩写

S符号位

D数据位

e指数位

例如:SeeeDDD,

DDD对应 D2,D1,D0

回车与换行的区别:

回车,光标回首行;换行,光标向下一行。

逻辑恒等式

A为一个逻辑值,A只能为0或1.

A and 0 = 0

A and 1 = A

A or 0 = A

A or 1 = 1

A and not A = 0

A or not A = 1

A xor 0 = A

A xor 1 = not A

A xor A = 0

A xor not A = 1

编译与链接

cl.exe:编译源码文件生成obj文件,obj文件与平台无关,Borland C (宝蓝C编译器)生成的obj文件可以给vc6使用;

参数/c表示只编译不链接,单个.c可以不加/c,让其自动链接;多个.c必须加/c防止自动链接。

link.exe:把obj转为操作系统能用的可执行文件。

VC用nmake编译makefile,用法:

1. 找到一个有makefile文件的工程

2. cmd中执行 nmake /f makefile

分享到:

0 条评论

昵称

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

沙发空缺中,还不快抢~