最近读《深入》一书遇到了非常多的问题,内容太杂较深,外国人的语言习惯也不一样,翻译过来的书翻译的怪怪的。所以读书进展很慢,我打算进度放缓,主攻《汇编语言》一书。
1.字
每台计算机都有一个字长 ,指明整数和指针的标称大小,同时字长也部分决定了虚拟地址空间的大小,如32位的80386CPU,其虚拟地址空间最大为4GB(2^32=4,294,967,296。4,294,967,296/1024/1024/1024=4GB,共有4,294,967,296个存储器单元地址,共4,294,967,296byte)。但是字长与地址总线没有对应关系。
2.数据大小
丢的文章中有篇写到了。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <climits> using namespace std;int main () { int n_int = INT_MAX; short n_short = SHRT_MAX; long n_long = LONG_MAX; long long n_llong = LLONG_MAX; cout << "int is " << sizeof (int ) << " bytes." << endl; cout << "short is " << sizeof (n_short) << " bytes." << endl; cout << "long is " << sizeof (long ) << " bytes." << endl; cout << "long long is " << sizeof (long long ) << " bytes." << endl; cout << "char* " << sizeof (char *) << " bytes." << endl; cout << endl; cout << "Maximum values:" << endl; cout << "int:" << n_int << endl; cout << "short:" << n_short << endl; cout << "long:" << n_long << endl; cout << "long long:" << n_llong << endl << endl; cout << "Minimum int value =" << INT_MIN << endl; cout << "Bits per byte =" << CHAR_BIT << endl; system ("pause" ); return 0 ; }
注意char*!也可以试试void *
,也是8字节 。
3.寻址和字节顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream> typedef unsigned char *byte_pointer; void show_bytes (byte_pointer start, int len) { int i; for (i = 0 ; i < len; i++) { printf ("%.2x" , start[i]); } printf ("\n" ); } void show_int (int x) { show_bytes ((byte_pointer)&x, sizeof (int )); } void show_float (float x) { show_bytes ((byte_pointer)&x, sizeof (float )); } void show_pointer (void *x) { show_bytes ((byte_pointer)&x, sizeof (void *)); } void test_show_bytes (int val) { int ival = val; float fval = float (ival); int *pval = &ival; int *ppval = &val; show_int (ival); show_float (fval); show_pointer (pval); show_pointer (ppval); } int main () { test_show_bytes (12345 ); system ("pause" ); return 0 ; }
结果的第一和第二行是12345
的整型和浮点型(浮点型为什么是这样以后在写)的十六进制表示,第三行是pval
内的值,即ival的地址,第四行是ppval
内的值,即val的地址。
34 fa 6f f1 fc
和下面第一行的fc f1 6f fa 34
有这显而易见的对应关系,这就牵扯到字节顺序。
pval 0x000000fcf16ffa34 int *
ppval 0x000000fcf16ffb90 int *
fc f1 6f fa 34
是本应是真正的值,只是在存储空间中并不是按照这种对应关系存储的。细心的话你会发现12345
的十六进制是3039
而不是3930
,显然,它是倒过来放的。低位有效数字在前,高位数字在后。这就是所谓的“小端法”。
假定十六进制数字0x1234567,其小端法表示和大端法表示分别为:
大端法:
0x100
0x101
0x102
0x103
01
23
45
67
小端法:
0x100
0x101
0x102
0x103
67
45
23
01
tips:十六进制与二进制转化。一个内存单元一字节,8bit,一个单元分为两组转化为十六进制。
《深入》一书中写到“大多数Intel兼容机都采用这种规则(小端法)”,“许多比较新的微处理器使用双端法”。
一些系统和机器的情况如下表:
(Windows为32位)
在64位的情况下,指针用的是八字节 !!!而32位的只有四字节。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> #include <iostream> using namespace std;int main () { int a=3 ; int b=a; int *p1=&a; int *p2=&b; cout<<p1<<' ' <<p2<<endl; system ("pause" ); return 0 ; }
这段代码在我的电脑上用不同编译器运行有不同的表现形式。(Windows10 64位 i7-3740MQ)
GCC 6.3.0(MinGW)
0x61ff14 0x61ff10
VS2017
0000007B8F58FD04 0000007B8F58FD24
注意到GCC的就是内存单元的编号,差了4字节,说明int a
和int b
是相邻存储的,但是编号形式是0x61ff14,是十六进制的。而VS中也是十六进制,相差20,十进制是32,也是4字节。GCC是按字节编号,而VS是按位编号。
回到39300000
和00e44046
这两个数字,其真实数字是3039 0000
和4640 e400
,其二进制分别是:
0011 0000 0011 1001 0000 0000 0000 0000
0100 0110 0100 0000 1110 0100 0000 0000
在补0对齐后
0000 0000 1100 0000 1110 0100 0000 0000 0000 00
0100 0110 0100 0000 1110 0100 0000 0000
注意中间有一部分是相同的,这就涉及到浮点数如何表示的问题了。