CSAPP第二章2.1总结by SixInNight

本文详细探讨了计算机系统中信息的表示和处理方式,包括十六进制表示法、字数据大小、寻址和字节顺序等核心概念。解析了小端法和大端法在内存中的应用,以及字符串、代码的表示方法。通过具体实例,如C语言中的字节表示和布尔代数介绍,加深对计算机底层原理的理解。
摘要由CSDN通过智能技术生成



2.1 信息存储

  • 8位的块或者字节作为最小的可寻址的内存单位
  • 机器级程序将内存视为一个非常大的字节数组 / 虚拟内存
  • 内存的每个字节都由一个唯一的数字来标识,称为它的地址所有可能地址的集合就称为虚拟地址空间
  • 例如,C语言中一个指针的值(无论它指向一个整数、一个结构或是某个其他程序对象)都是某个存储块第一个字节的虚拟地址。C编译器还把每个指针和类型信息联系起来,这样都可以根据指针值的类型,生成不同的机器级代码来访问存储在指针所指向位置处的值
  • 每个程序对象可以简单地视为一个字节块,而程序本身就是一个字节序列

2.1.1 十六进制表示法

  • 十六进制hexadecimal)数来表示位模式。用十六进制书写,一个字节的值域为0016 ~ FF16
  • x = 2n,当n表示成 i + 4j (其中0≤i≤3)的形式,可以把x写成开头的十六进制数为 i ,后面跟着 j 个十六进制的0。比如,x=2048=211,我们有n=11=3+4×2,从而得到十六进制表示0x800
  • x = q × 16 + r,然后我们用十六进制数字表示的 r 作为最低位数字,并且通过对 q 反复进行这个过程得到剩下的数字。例如,十进制314156的转换:
    • 314156 = 19634 × 16 + 12 (C)
    • 19634 = 1227 × 16 + 2 (2)
    • 1227 = 76 × 16 + 11 (B)
    • 76 = 4 × 16 + 12 (C)
    • 4 = 0 ×16 + 4 (4)
    • 由此读出十六进制表示为0x4CB2C

2.1.2 字数据大小

  • 对于一个字长为 w 位机器而言,虚拟地址的范围为 0 ~ 2w-1程序最多访问 2w 个字节


2.1.3 寻址和字节顺序

  • 排列表示一个对象的字节有两个通用的规则
    小端法little endian)—— 最低有效字节在最前面;
    大端法big endian)—— 最高有效字节在最前面;

  • 考虑一个 w 位的整数,其位表示为 [ xw-1,xw-2,…,x1,x0 ],其中 xw-1 是最高有效位,而 x0 是最低有效位。假设 w 是8的倍数,这些位就能被分组成字节,其中最高有效字节包含位 [ xw-1,xw-2,…,xw-8 ],而最低有效字节包含位 [ x7,x6,…,x0 ],其他字节包含中间的位。某些机器选择在内存中按照前一种规则从最低有效字节到最高有效字节的顺序存储对象;另一些机器按照后一种规则从最高有效字节到最低有效字节的顺序存储

  • 假设变量 x 的类型为 int,位于地址 0x100 处,它的十六进制值为 0x01234567。地址范围 0x100 ~ 0x103 的字节顺序依赖于机器的类型:
    (注意,在字 0x01234567 中,高位字节的十六进制值为 0x01,低位字节的十六进制值为 0x67)

    大端法小端法
    0x1000x1010x1020x1030x1000x1010x1020x103
    0123456767452301

  • 反汇编disassembler)是一种确定可执行程序文件所表示的指令序列的工具

  • 下面这段C代码,使用强制类型转换来访问和打印不同程序对象的字节表示。用 typedef 将数据类型 byte_pointer 定义为一个指向类型为 “unsignedchar” 的对象的指针。这样一个字节指针引用一个字节序列,其中每个字节都被认为是一个非负整数。第一个例程 show_bytes 的输入是一个字节序列的地址,它用一个字节指针以及一个字节数来指示。该字节数指定为数据类型 size_t,表示数据结构大小的首选数据类型。show_bytes 打印出每个以十六进制表示的字节。C格式化命令 “%.2x” 表明整数必须用至少两个数字的十六进制格式输出

	#include<stdio.h>
	
	typedef unsigned char *byte_pointer;
	
	void show_bytes(byte_pointer start, size_t len) {
		size_t 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 *));
	}

2.1.4 表示字符串

  • C语言中字符串被编码以一个 null(其值为0)字符结尾的字符数组。以参数 “12345” 和 6(包括终止符)来运行例程 show_bytes,我们将得到结果 31 32 33 34 35 00
  • 注意,十进制数字 x 的 ASCII 码正好是 0x3x,而终止字节的十六进制表示为 0x00
  • 在使用 ASCII 码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因而,文本数据比二进制数据具有更强的平台独立性

2.1.5 表示代码

  • 二进制代码是不兼容的,二进制代码很少的能在不同机器和操作系统组合之间移植
  • 机器没有关于原始程序的任何信息,除了可能有些用来帮助调试的辅助表以外。从机器角度来看,程序仅仅只是字节序列

2.1.6 布尔代数简介

~NOT
&AND
|OR
^EXCLUSIVE-OR异或
  • 位向量 a = [ 01101001 ] 表示集合 A = { 0,3,5,6 },而 b = [ 01010101 ] 表示集合 B = { 0,2,4,6 }。使用这种编码集合的方法,布尔运算 |& 分别对应于集合的,而 ~ 对应于集合的。运算 a&b=[ 01000001 ],而 A∩B={ 0,6 }

2.1.7&8&9 C语言中的运算

  • 位级运算:

    C的表达式二进制表达式二进制结果十六进制结果
    ~0x41 ~[ 0100 0001 ][ 1011 1110 ]0xBE
    ~0x00 ~[ 0000 0000 ][ 1111 1111 ]0xFF
    0x69 & 0x55[ 0110 1001 ] & [ 0101 0101 ][ 0100 0001 ]0x41
    0x69 | 0x55[ 0110 1001 ] | [ 0101 0101 ][ 0111 1101 ]0x7D

  • 逻辑运算:

    表达式结果
    ! 0x410x00
    ! 0x000x01
    !! 0x410x01
    0x69 && 0x550x01
    0x69 || 0x550x01

  • 移位运算:(算术右移是在左端补 k 个最高有效位的值)

    操作
    参数 x[ 0110 0011 ] [ 1001 0101 ]
    x << 4[ 00110000 ] [ 0101 0000 ]
    x >> 4(逻辑右移)[ 0000 0110 ] [ 0000 1001 ]
    x >> 4(算术右移)[ 0000 0110 ] [ 1111 1001 ]

补充

  1. 关于移动 k ≥ w 位
  2. 未完待续
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值