[TOC]

# 前言
在刚开始学习嵌入式时我们就遇到各种进制之间的换算,十六进制、十进制、八进制、二进制等等,一开始会经常在各种进制之间迷失自我;
在深入学习或者做项目或者工作时我们也经常要查看各种芯片的数据手册(datasheet),手册里面一般都是使用十六进制表示各种地址。
这时我们就会遇到类似这样的问题:
- 为什么 0x100 是 256Bytes([字节](https://baike.baidu.com/item/%E4%BD%8D%E3%80%81%E5%AD%97%E8%8A%82%E3%80%81%E5%AD%97/15650262?fr=aladdin)) 大小?
- 0x400 是 1KB 大小?
- 0x800是 2KB 大小?

下面我们就来解决这个疑惑!

# 数据单位标准
我们都知道数据单位有:bit、byte、word、KB、MB、GB、TB等等,他们之间的换算很简单,例如:

```bash
- 1TB=1024GB
- 1GB=1024MB
- 1MB=1024KB
- 1KB=1024B(Byte)
- 1B=8bit
```

从上面的换算我们可以不难理解下面的两个基本约定:

- bit(比特):bit是数据的最小单位,通常简写为b。在计算机中通常用1和0来表示。
- Byte(字节):数据存储的基本单位,通常简写为B。通常:1Byte=8bit。

但是这些都是谁规定的呢?我们得先要解决这个疑惑。

## 两种标准
目前,有两种比较流行的单位:一种为[SI(International System of Units,国际单位制)](https://en.wikipedia.org/wiki/International_System_of_Units)制定的标准,采用十进制换算。例如:

```bash
1 MB = 106 bytes = 1 000 000 bytes = 1000 kilobyte
1024 MB = 1 gigabyte (GB)
```

其中kilo、giga等称为十进制前缀,通常简写为KB、GB等。

另一种则为[IEC(International Electrotechnical Commission,国际电工委员会)](https://en.wikipedia.org/wiki/International_Electrotechnical_Commission)于[1998年2月](https://physics.nist.gov/cuu/Units/binary.html)制定的标准([IEC 60027-2](https://webstore.iec.ch/publication/93)),采用二进制换算。例如:

```bash
1 MiB = 2^20 bytes = 1 048 576 bytes = 1024 kibibytes
1024 MiB = 1 gibibyte (GiB)
```

其中kibi、gibi等称为二进制前缀,通常简写为KiB、GiB等。

下图是两种单位标准的[wiki](https://en.wikipedia.org/wiki/Byte)截图,摘自[wiki](https://en.wikipedia.org/wiki/Byte#Multiple-byte_units):
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210421224309102.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTgxMjM2,size_16,color_FFFFFF,t_70)

IEC制定的这个标准用于在一些更严格的场景下(希望使用二进制换算的情况)替换SI的标准,目前已为大多数组织所接受,像现在的许多Linux发行版也采用这种单位。

在本文中我们只关注我们常用到的 IEC 制定的标准,所有的讨论均是在 IEC 制定的 IEC 60027-2 标准基础上。

拓展阅读:

- [https://en.wikipedia.org/wiki/Byte](https://en.wikipedia.org/wiki/Byte)
- [https://simple.wikipedia.org/wiki/Mebibyte](https://simple.wikipedia.org/wiki/Mebibyte)

# 0x400为什么是1KB大小?
为了说这个问题,我们以 2440 的芯片手册为例,下面的图是 NAND闪存映射:

> 下面图引用自 S3C2440A_UserManual_Rev13.pdf :p222

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210419185113659.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTgxMjM2,size_16,color_FFFFFF,t_70)
我们重点看 ``0x4000 0000 - 0x4000 0FFF`` 这段内存空间。图中说明这个4kb的空间是分配给BootSRAM,这个 ``4KB`` 结果的换算过程:

```bash
1. 0x4000 0FFF - 0x4000 0000 = 0x0000 0FFF
2. 0x0000 0FFF 的十进制是 4095 (Bytes)
3. (4095+1) / 1024 = 4 (KB)
```
> 为什么 0x0000 0FFF 的十进制是 4095 ,而且这就是代表 (4095+1) 个字节(也就是4KB)呢?下面我们一起来解开这个疑惑:

下图是2440的内存布局图 ``(0x0000 0000 - 0xFFFF FFFF) ``。
2440的CPU是32bit的,地址总线一共有 ``32(2^5)`` 根,可以索引的地址范围是`` 0 - 2^32 (0x0000 0000 - 0xFFFF FFFF)`` ,也就是 ``4GB`` 的空间。

那么这个 4GB 是怎么得来的呢?
下面的图已经给出了很直观的答案了,2440的CPU是 ``32`` 位的,所以表示的范围是:

```bash

0000 0000 0000 0000 0000 0000 0000 0000 (0x0000 0000)

1111 1111 1111 1111 1111 1111 1111 1111 (0xFFFF FFFF)
```

一个字节有8位,从下面的图可知,一共有 ``0xFFFF FFFF`` 个字节,也就是 ``4,294,967,295`` 个字节( ``0xFFFF FFFF`` 转换后的十进制),所以大小为:`4,294,967,295 Bytes = 4,194,305KB = 4095MB `
但是这里为什么不是 `4096` 呢?因为我们计算的范围是 `0x0000 0000 - 0xFFFF FFFF` ) ,并没有算第1个字节(Byte),所以上面的应该是一共有 ``0xFFFF FFFF+1`` 个字节,也就是:`4,294,967,296 Bytes = 4,194,306KB = 4096MB = 4GB `
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210510145740134.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTgxMjM2,size_16,color_FFFFFF,t_70)

> 上面的案例基于 2400,其他芯片也是一样的思路分析即可。不管他是8位、16位、32位还是64位,我们只要知道他们的能表示的最大范围即可
# 回到开始的问题
到这里我们就能理解为什么在 2440的芯片手册中,分配给BootSRAM的 0x4000 0000 - 0x4000 0FFF 是 ``4KB`` 大小了 。

那么我们来解决一开始提出的问题: `为什么0x400是1KB大小?`

0x400转换的十进制为:`1024`,也就是有 1024 个字节(Byte),
1KB的换算过程:`1024(Byte)/1024=1kb`。

用这种思路我们就可以理解为什么, 0x100 是 256 个字节(Bytes)、0x800是 4096 个字节(Bytes)也就是 4KB。

# 附录1:存储单位之间的换算
| | |
| :-- | :-- |
| 1 Byte(B) | 8 bit |
| 1 Kilo Byte(KB) | 1024B |
| 1 Mega Byte(MB) | 1024 KB |
| 1 Giga Byte (GB)| 1024 MB |
| 1 Tera Byte(TB)| 1024 GB |
| 1 Peta Byte(PB) | 1024 TB |
| 1 Exa Byte(EB) | 1024 PB |
| 1 Zetta Byte(ZB) | 1024 EB |
| 1Yotta Byte(YB)| 1024 ZB |
| 1 Bronto Byte(BB) | 1024 YB |
| 1Nona Byte(NB)|1024 BB |
| 1 Dogga Byte(DB)|1024 NB |
| 1 Corydon Byte(CB)|1024DB |
| 1 Xero Byte (XB)|1024CB |
# 附录2:常见的16进制地址及其对应容量
| 十六进制 | 大小 |
| :-- | :-- |
| 0x100 | 256B |
| 0x200 | 512B |
| 0x400 | 1KB |
| 0x800 | 2KB |
| 0xC00 | 3KB |
| 0x1000 | 4KB |
| 0x2000 | 8KB |
| 0xF000 | 60KB |
| 0x1 0000 | 64KB |
| 0x2 0000 | 128KB |
| 0xF 0000 | 960KB |
| 0x10 0000 | 1MB |
| 0x20 0000 | 2MB |
| 0xF0 0000 | 15MB |
| 0x0100 0000 | 16MB |
| 0x0200 0000 | 32MB |
| 0x0F00 0000 | 240MB |
| 0x1000 0000 | 256MB |

最新文章

  1. 这是一个比较全的Android UI 组件
  2. Mybatis学习错误之:重复加载mapper.xml
  3. MAC中查看Python安装路径
  4. 挂载光盘与rpm安装
  5. HDU 4123(树的直径+单调队列)
  6. 《c程序设计语言》读书笔记-字符型0-9转为数字0-9
  7. python 读取机器信息
  8. Xcode 7:Storyboard Reference、Strong IBOutlet以及Scene Dock
  9. twisted(2)--聊天系统
  10. Thinkphp中的volist标签(查询数据集(select方法)的结果输出)用法简介
  11. Leetcode刷题C#版之Toeplitz Matrix
  12. mysql 表结构转excel表格
  13. ELK 构建 MySQL 慢日志收集平台详解
  14. mockjs在vue中的使用
  15. Navicat 的安装及破解
  16. html垂直居中
  17. 在SQL Server中用好模糊查询指令LIKE (转载)
  18. 服务器环境配置安装(mysql+redis+nodejs+nginx)
  19. 微信小程序支付C#后端源码
  20. UWP入门——应用数据和设置

热门文章

  1. java为什么是一次编译,多次解释
  2. 【补档_STM32单片机】脉搏波采集显示硬件设计
  3. 日常Bug排查-消息不消费
  4. 在命令行模式下查看Python帮助文档---dir、help、__doc__
  5. 语义分割:基于openCV和深度学习(二)
  6. GPU编程和流式多处理器(四)
  7. SpringBoot原理深入及源码剖析(一) 依赖管理及自动配置
  8. fiddler抓取手机APP包相关的设置
  9. 【NX二次开发】判断面是否相切,相切面。
  10. 重磅!GitHub官方开源新命令行工具