以下仅为个人学习的记录,如有疏漏不妥之处,还请不吝赐教。
字节(byte)这个术语由 Werner Buchholz在1956年创造的。在此之前,字节通常称为syllable.
历史上,字节并非一定是8位的,但现在基本都是以8位作为1个字节。最开始字节是用来为字符编码的。C语言中的用char类型为字符编码,占1字节。可是1个字节最多只能存放256组合,也就是说,1个字节最多能表示256种字符。因此需要多个字节来表示数据。这就引出一个问题。
多字节数据怎么存储?字节的排列顺序?
在几乎所有的机器中,多字节数据都是被存储为连续的字节序列,数据的地址为所使用字节中最小的地址。
多字节数据还存在另一个问题:字节的排列问题。通常数据的字节排列有两个通用的规则:大端法(big endian)和小端法(little endian)
下面以0x12345678为例说明这个4字节数据在内存中的存储方式:
内存地址 -> | 0x1(最小存储地址) | 0x2 | 0x3 | 0x4 |
大端法 -> | 12(最高有效字节) | 34 | 56 | 78 |
小端法 -> | 78(最低有效字节 | 56 | 34 | 12 |
可见,大端法和小端法是相反的。大端法最高有效字节在前,小端法最低有效字节在前。下面用C语言测试当前运行的系统是采用哪种存储方式。
#include <stdio.h> void showByte() { int num = 0x12345678; char* cp = (char*) &p; for(int i = 0; i < sizeof(int); i++) {
if(0x78 == *cp) printf("小端法: ");
else printf("大端法: "); printf("0x%x ", *cp); // 输出:0x78 0x56 0x34 0x12 因此是小端法存储。 cp++; } } int main() { showByte(); }
C语言中的目标文件中没有数据类型,那CPU如何知道在内存读取多字节数据呢?
根据上面的showByte函数生成的汇编代码知,每条数据操作指令都带有操作数的字节大小,如第14行的movq -8(%rbp), %rax 表示要往内存地址-8(%rbp)中读取4个字节到%rax寄存器。CPU通过指令知道读取多字节数据。
showByte: 1 pushq %rbp 2 .seh_pushreg %rbp 3 movq %rsp, %rbp 4 .seh_setframe %rbp, 0 5 subq $48, %rsp 6 .seh_stackalloc 48 7 .seh_endprologue 8 movl $305419896, -16(%rbp) 9 leaq -16(%rbp), %rax 10 movq %rax, -8(%rbp) 11 movl $0, -12(%rbp) 12 jmp .L2 13 .L3: 14 movq -8(%rbp), %rax 15 movzbl (%rax), %eax 16 movsbl %al, %eax 17 movl %eax, %edx 18 leaq .LC0(%rip), %rcx 19 call printf 20 addl $1, -12(%rbp) 21 addq $1, -8(%rbp) 22 .L2: 23 movl -12(%rbp), %eax 24 cmpl $3, %eax 25 jbe .L3 26 nop 27 addq $48, %rsp 28 popq %rbp 29 ret
参考文献:
《深入理解计算机系统》第三版