汇编语言基础--机器级数据存储
目前机器级的编程,不再像几十年前对于一个程序员来讲,是需要熟练掌握的技术,现在有很多人甚至不太了解机器指令系统。由于计算机高层的抽象愈加完善,软件项目的构建都可以使用已有的框架来拼凑,机器指令会越来越像天方夜谭。但我认为的计算机系统知识搭建会比较像TCP/IP协议的架构,虽然并不必要精通底层的东西,但了解这些,会在问题发生的时候提供很大的便利。
机器级的编程之所以总结归纳CPU相关的标签,主要是因为个人感觉而言和CPU硬件知识的耦合性比较大,从抽象分类的层面,无法放在操作系统级或者编程语言级。机器指令级的编程会主要介绍两个方面,一是机器级数据存储,二是汇编操作指令概述。虽然是概述,但是由于内容过多,本文主要讲述机器级数据存储。
数据存储
存储大小:
字节(8位,byte)是计算机上最小的可寻址单元。每一个位用来存储二进制位值。(注意十六进制、十进制与二进制的转换)。
字长(word)反映cpu一次并行处理的最大二进制位数,一般整数和指针的大小为一个字长。这意味着虚拟地址的大小由字长来决定,为2^w个字节。另一方面,更长的字长意味着cpu能够一次计算的数更大。如果32位的机器计算结果超过32位而小于64位,需要两次或多次计算。但是64位的机器一次即可以完成。
c语言的基本数据类型有字符(char)、整型(int,根据存储大小又可以分为long、(int)、short)、浮点型(float,double)和指针。下图是C语言常见类型和存储大小的表。
| C类型 | 32位机器(字节) | 64位机器(字节) |
| char | 1 | 1 |
| short int | 2 | 2 |
| int | 4 | 4 |
| long int | 4 | 8 |
| 指针 char* | 4 | 8 |
| float | 4 | 4 |
| double | 8 | 8 |
存储顺序:
多字节对象在机器上存储时面临高位和低位字节的排列顺序问题。如对于整型0x01234567:
大端法的存储方式是,数据的高位存储在低地址字节上,而数据的低位存储在高的地址上(如下图所示)。

小端法的存储方式和大端法完全相反,数据低位存储在低地址的字节上。

本身大端和小端数据存储都是可以的,但在一些情况下存在问题。由于大端机器发送数据到小端机器时会乱序,因此网络的字节顺序必须统一。另一方面,读取机器级代码时,如何解码到汇编也需要注意大端机和小端机的不同。第三种情况是在编程中用强制类型转换,以不同于一个值被创建的方式,来使用这个值时,会出现转换完全出乎你意料的情况。
数据编码:
1.整数储存表示:
在介绍整数的编码形式之前,需要了解几种编码方式。
原码的编码方式规定最高位为符号位,0代表正,1代表负。其他位为整数绝对值的二进制编码。如9的二进制为1001,假设采用4字节的整型存储方法,9以00000000 00000000 00000000 00001001存储,而-9以10000000 00000000 00000000 00001001存储。
反码是为了解决相同绝对值的正负数相加不为0的情况。反码的编码方式规定,正整数以原码的方式存储,而负数需要在原码的基础上,除了符号位,其他位上都需要取反。这个时候-9的反码表示为11111111 11111111 11111111 11110110。这个时候9+(-9)刚好为反码的-0。这里出现了另一个问题,0有正0和负0两种编码。
补码的编码方式规定,正整数以原码方式存储,负数需要在补码编码的基础上加1。此时-9的补码表示为11111111 11111111 11111111 11110111。这个时候由于负0的反码加1后和正0的编码方式是一致的,因此0只有一种编码方式。这种编码方式同样可以解决相同绝对值的正负数相加不为0的问题。
整型的计算机编码采用补码的方式。
在C/C++语言中,存在有符号数和无符号数(使用signed 和 unsigned标识)。因此存在着有符号数和无符号数之间的转换,这中间存在着扩展、截断和溢出的问题。但java中默认不存在无符号整型,避开了这个问题。
2.浮点数表示:
IEEE浮点数标准用 V = 来表示一个浮点数。s代表符号位,m为有效数,e为指数。浮点数的域划分为三段,符号位s,k位指数域exp, n位小数域frac。 float为32位,4字节,s=1,k=8, n= 23; double 为64位,8字节,s=1,k=11,n=52。
这种编码其中存在着三种值。
规格化值:exp不全是0也不全是1,则指数E=e-bias,e为exp的无符号数,bias为2k-1(float为k为8-1,double为11-1),则E的范围为-126~127或-1022~1023。(与有符号数不一样,有符号数是负值多一个,主要原因是-1)。此时小数域frac,认为最高位默认值为1,小数域只存储小数域值(.以后的数)。
非规格化值:exp全为0时,e为0,但是指数E=1-bias(而非0-bias,为了平滑过渡,通过增加一个1,可以弥补非规格化数frac最高位没有的1),此时frac最高位为0,不为默认的1.好处1可以表示0,好处2可以表示接近0的数。
特殊值:exp全为1,小数域全为0,符号位为0时表示+∞,为1时可以表示-∞。小数域不为0时表示NaN。
3.字符编码:
字符编码有多种体系,比如 ASCII、Unicode编码,其中并不存在特别难以理解的问题,可以参考相关资料。
本系列文章:
汇编语言基础--机器级数据存储

浙公网安备 33010602011771号