您的位置:首页 > 理论基础

深入理解计算机系统(4)

2015-11-12 19:35 302 查看

2.1.4 寻址和字节顺序

对于跨字节的对象而言,最重要的是两点,一个是对象的首地址,另外一个则是字节顺序。

对于X86系统而言,为小端系统。小端其实可以理解为咱们平常的数字顺序颠倒,比如01 23 45 67,表示的其实是67 45 23 01,也就是把越大的放在越后面。而大端则是把越大的放在越前面。也就是说01 23 45 67在大端系统而言,表示的就是01 23 45 67。这么说很不直观,来举个例子吧,比如在x86机器上,使用相同的编译器,每次只申请一个变量,第一次申请的是long
long类型,printf为其地址为0x22ff18。请问下一次只申请一个int变量,打印其地址为多少?这个问题是我自己想的,其实有个假设就是很多东西都是不变的。我来说一下这个问题的答案吧,应该是0x22ff1c。这个题目其实还需要知道栈空间的增长方向是往地址减小的方向。如下图所示:



也就是说小端的话,01 23 45 67,也就是向右的方向是增长的方向。而大端反之。可以简单记为小端增,大端减。小端需要倒置,而大端不变。
以下的例子是课本中使用C语言来打印不同对象对应的字节序列的。
#include <stdio.h>

typedef unsigned char* bype_pointer;

//显示字节
void show_byte(char* bype_pointer, int len){
for (int i=0; i<len; ++i){
printf(" %.2f", bype_pointer[i]);
}
printf("\n");
}

void show_int(int x){
show_byte((bype_pointer)(&x), sizeof(int));
}

void show_float(float x){
show_byte((bype_pointer)(&x), sizeof(float));
}

void show_pointer(void *x){
show_byte((bype_pointer)(&x), sizeof(void *));
}<pre name="code" class="cpp">void test_show_bytes(int val){
int ival = val;
float fval = (float)(ival);
int *pval = &ival;
show_int(ival);
show_float(fval);
show_pointer(pval);
}



可知Linux 32、Windows 和 Linux 64是小端机器,而Sun是大端机器。

练习题 2.5

int val = 0x87654321;
byte_pointer valp = (byte_pointer)&val;
show_bytes(valp, 1);
show_bytes(valp, 2);
show_bytes(valp, 3);
在小端和大端机器上面结果分别为多少?
小端:21 2143 214365              
大端:87 8765 876543

注意:虽然字节序有可能变化,但是每个字节是不变的。比如小端应该为21 43 65 87,而不是12 34 56 78。



练习题2.6

使用show_int和show_float,我们确定整数的十六进制为0x00359141,而浮点数的十六进制为0x4A564504。

A.请写出两个数的二进制表示

0x00359141: 0B              1101011001000101000001
0x4A564504:   0B1001010010101100100010100000100

B.最多有多少位匹配?
20位
C.串中什么部分不匹配
前面和最后面。

2.15 表示字符串

在使用 ASCII 码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因而,文本数据二进制数据具有更强的平台独立性。

而Unicode编码,使用32位来表示字符。而UTF-8将每个字符编码为一个字节序列。这样就和ASCII码中的英文编码一致了。

2.16 表示代码

即使是完全一样的进程运行在不同的操作系统上也有不同编码的规则,因此二进制是不兼容的。

计算机系统的一个基本概念是从机器的角度来看,程序仅仅只是字节序列。机器没有任何源程序的任何信息。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息