字節與小端、大端法存儲。
阿新 • • 發佈:2019-02-19
spa sizeof 另一個 深入理解 eight 代碼 tar http 數據類型
以下僅為個人學習的記錄,如有疏漏不妥之處,還請不吝賜教。
字節(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
參考文獻:
《深入理解計算機系統》第三版
字節與小端、大端法存儲。