> For the complete documentation index, see [llms.txt](https://xu-an.gitbook.io/sec/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xu-an.gitbook.io/sec/lan/huibian.md).

# 汇编

### 1、课程概要

1、什么是机器语言&#x20;

加：0100 0000 \
减：0100 1000 \
乘：1111 0111 1110 0000 \
除：1111 0111 1111 0000&#x20;

缺点：不方便记忆

2、汇编语言：

由机器语言发展而来，可用符号表示数值间的运算

加：INC EAX → 0100 0000\
减：DEC EAX 0100 1000 \
乘：MUL EAX 1111 0111 1110 0000 \
除：DIV EAX 1111 0111 1111 0000

优势：相对于机器语言，更简单 \
劣势：不符合人类的思维范式

编译器： 可将汇编指令转换为机器语言的工具

3、C语言：&#x20;

加：A+B 0100 0000 \
减：A-B 0100 1000 \
乘：A\*B 1111 0111 1110 0000 \
除：A/B 1111 0111 1111 0000

C语言属于高级语言，更加贴近人类的思维方式

4、C与C++的关系&#x20;

1. &#x20;C与C++其实没有本质区别，只是编译器做的事情越来越多，越来越强大
2. C语言是C++的基础

5、学习汇编的原因

1. 一个不懂汇编的人，都是不懂原理的
2. 如果从事安全行业，汇编是必须要掌握的基础（外挂开发等）
3. 对于正向开发，懂汇编可以做的更好，潜力更大

6、学习环境

1. VC6
2. VS2010，2013，2016
3. 选择VC6的原因：越是新版本的编译器，在编译的时候添加的细节代码会更多，不利于学习

win7下安装VC6：[教程链接](https://jingyan.baidu.com/article/6b1823096f76fbba58e159d3.html)，[VC6安装包](http://pcr1.pc6.com/rm/VC6.0.rar)

### 2、进制

1、学习进制的原因

计算机只认识二进制，为了更好理解计算机，就需要深刻理解进制

2、学习进制的障碍

总以十进制为依托，需要运算的时候也是先转换为10进制，这种学习方法是错误的

想要学好进制，就要先忘掉十进制，忘掉进制间的转换

3、进制的定义

| 进制  | 组成                          | 规则   |
| --- | --------------------------- | ---- |
| 八进制 | 有八个符号组成，0 1 2 3 4 5 6 7     | 逢八进一 |
| 十进制 | 有十个符号组成，0 1 2 3 4 5 6 7 8 9 | 逢十进一 |
| N进制 | 有N个符号组成                     | 逢N进一 |

4、进制的书写

在进制的运算中，没有必要对进制进行转换，可以直接进行计算

| 进制 | 写法                     |
| -- | ---------------------- |
| 1  | 0，1，11，111，1111，11111  |
| 3  | 0，1，2，10，11，12，21，22   |
| 7  | 0，1，2，3，4，5，6，10，11，12 |

5、你能理解1+1=3吗？

学习进制，就要理解进制的深度，而不是表面现象

如果将进制用在加密解密方向，就会给解密的人带来很大的困扰

### 3、进制的运算&#x20;

每一种进制的体系都是完美的，不需要转换成其他进制进行运算

&#x20;1、八进制运算

2+3=?(5)  2\*3=?(6)  2+3=?(5)  4+5=?(11)  4\*5=?(24)  277+333=?(277+333=7+3(12)+(130)+2+4(6)=632)  276\*54=?()  237-54=?()  234/4=?() &#x20;

0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20,21,22,23,24

2+3为从2开始，往后查3个数，其他相同

制作八进制的加法表与乘法表：

0，1，2，3，4，5，6，7，10，11，12，13，14，15，16，17，20，21，22，23，24，25，26，27

![加法表](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmWM-Gxp7CwIuPrb3F%2F-MDm_HpBpJxuMLVkgkH8%2Fimage.png?alt=media\&token=0e920cb6-5c4d-4630-b226-479abd8de5b2)

![乘法表](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmWM-Gxp7CwIuPrb3F%2F-MDmgq8E6BFNdi23Dgra%2Fimage.png?alt=media\&token=fe0df1b5-d4a3-4ac6-8b07-5ffffc1d32e7)

乘法表的本质，也是查询数字

&#x20;进制总结：\
每种进制都是完美的，他自身就是一个完整的体系，可以直接进行各种运算

### 4、二进制简写形式

1、计算机为什么使用二进制

计算机是需要用电的，电路只有两种状态：1 真（通电），0 假（未通电） 。\
计算机中存储的任何文件，接收的任何指令都是由0和1组成的（查看一个.exe程序）

&#x20;查看EXE文件使用工具为：UltraEdit

其中内容为：

文件的地址位：文件中的内容：UE的注释

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmr691y4DL2CMUnnQ1%2F-MDnDQBKvf1-tuxmirYe%2Fimage.png?alt=media\&token=75bedf7b-c5d9-434d-9c29-08993f718709)

&#x20;2、二进制的简写形式

二进制：从0写到1111\
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

这种二进制使用起来太麻烦，改写成更简单一点的符号：

0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\
这就是十六进制了，中国古代时候已经开始使用十六进制了

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmr691y4DL2CMUnnQ1%2F-MDnBWZU30KJjtJR4dWq%2Fimage.png?alt=media\&token=33e96aba-c8f4-4ce1-805a-184fc05e44a6)

建议：写代码的时候要习惯十六进制，最好不要用十进制

十六进制：可读性更强

3、熟练掌握进制之间的转换

### 5、数据宽度

1、数据宽度

数学上的数字，是没有大小限制的，可以无限大，但在计算机中，由于的硬件制约，数据都是有长度限制的（数据宽度），超出宽度的数据会被丢弃

&#x20;2、计算机中常见的数据宽度

| 单位             | 宽度 | 存储范围       |
| -------------- | -- | ---------- |
| 位（BIT）         | 1  | 0-1        |
| 字节（BYTE）       | 8  | 0-FF       |
| 字（WORD）        | 16 | 0-FFFF     |
| 双字（DOUBLEWORD） | 32 | 0-FFFFFFFF |

&#x20;位是计算机中存储数据的最小单位\
一个字节能存储8个位\
字有16位\
双字能存储32个位

讲解中的示例代码：

```c
// firstCreckme.cpp : defines the entry point for the console application 
//

# include "stdafx.h"
# include <stdio.h>

int main(int argc,char*argv[])
{
    char x = 0x1FF;
    // char 要使用的容器是8位的
    // int  要是用的容器是32位的
    printf("%x\n ",&x);
    
    return 0;
}
```

### 6、有符号数和无符号数

&#x20;在不同文件中，0和1的含义都是不同的

1、无符号数的编码规则

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmr691y4DL2CMUnnQ1%2F-MDnIQkRZo5k-8WSg_Qr%2Fimage.png?alt=media\&token=f6abd31f-db84-4502-9e8a-9ad3fcce0507)

十六进制显示的话，则是：0x9A，十进制是：154\
文件不同，解析方法不同

2、有符号数，正数编码规则：1A&#x20;

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDmr691y4DL2CMUnnQ1%2F-MDnIQkRZo5k-8WSg_Qr%2Fimage.png?alt=media\&token=f6abd31f-db84-4502-9e8a-9ad3fcce0507)

&#x20;如果最高位是1，则为负数；如果最高位是0，则为正数

如果一个数是有符号数，且最高位是0，那么这个数一定是正数

```
int main(int argc,char* argv[])
{
    int x = 0x1A000000;
    printf("以无符号形式显示：%v\n",x);
    printf("以有符号形式显示：%d\n",x);
    
    return 0;
}
```

当数字为正数时，有符号与无符号的显示结果是一样的

### 7、数字的编码

1、编码规则

不同的文件有不同的编码规则\
有符号数与无符号数解析成果是一样的，若首位是0\
负数的编码规则与正数不同

2、有符号数的编码规则

原码：最高位为符号位，其余各位是数值本身的绝对值\
\
反码：\
正数：反码与原码相同\
负数：符号位为1，其余位对原码取反\
\
补码：\
正数：补码与原码相同\
负数：符号位为1，其余位对原码取反加1

3、举例说明

| 例子 | 原码        | 反码        | 补码        |
| -- | --------- | --------- | --------- |
| 1  | 0000-0001 | 0000-0001 | 0000-0001 |
| 6  | 0000-0110 | 0000-0110 | 0000-0110 |
| -1 | 1000-0001 | 1111-1110 | 1111-1111 |
| -7 | 1000-0111 | 1111-1000 | 1111-1001 |

总结：

1. 正数原码存储（编码规则）
2. 负数补码存储（编码规则）

4、假设数据宽度为1BYTE（8 BIT）

无符号数：0  1  2  3  4  5  ........  FF  （10进制255）\
有符号数：\
正数：0......7F\
负数：FF......80

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDnQatteFU_jFE1j30X%2F-MDnR_-Cd0-1GWYn3iiS%2Fimage.png?alt=media\&token=39db88ec-0a72-4e40-b431-1a838c5a9d12)

5、假设数据宽度为DOUBLEWORD（双字）

无符号数：0  1  2  3  4  5  ........  FFFFFFFF  \
有符号数：\
正数：0......7FFFFFFF\
负数：FFFFFFFF......80000000

### 8、计算机的运算

计算机是通过位运算来做的运算

为什么要学习位运算？

1. 有些功能必须通过位运算才能实现：比如写调试器，判断CPU的各种状态位
2. 大公司面试题：比如2\*8的效率最高的实现方式

1、与运算 and(&)

两个数都为1时，结果才是1

![两个开关都闭合时，灯泡才会亮](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDnQatteFU_jFE1j30X%2F-MDnTDZF61qibQUNl_dP%2Fimage.png?alt=media\&token=507a3a34-0d07-4cb1-ab10-4452d2a94fef)

比如：1011-0001&1011-0000=10010000

2、或运算  or (|)

只要有一个为1就是1

![一个开关闭合，灯泡会亮](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDnQatteFU_jFE1j30X%2F-MDnTuBplEjv-Zi2Zj75%2Fimage.png?alt=media\&token=5c672a6c-7b74-457d-94ba-b0f0ea3e5b1a)

比如：1011-0001|1101-1000=1111-1001

3、异或运算    xor(^)

不一样的时候是1

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDnUG78hR3_g5y-AXQA%2F-MDnUXfKZLkTTarKU73X%2Fimage.png?alt=media\&token=6058bf77-63a4-4203-806d-9d82c0cea718)

比如：1011-0001^11011000=01101001

4、非运算  not(\~)

0就是1，1就是0\
注意：非运算只需要一个数字，单目运算

比如：1101-1000 = 0010-0111

5、移位运算

5-1、左移：\
各二进位全部左移若干位，高位丢弃，低位补0\
比如： shl(<<) 1101-1000左移2位为： 0110-0000

5-2、右移：\
各二进位全部右移若干位，低位丢弃，高位补0或者补符号位

比如： &#x20;

```c
shr 1101-0101 0011-0101    #shr补0
对应C语言（>>）
unsigned int a = 10;
printf("%d\n",a>>2);

sar 1101-0101 1111-0101    #sar补符号位
对应C语言（>>）
int a = 10;
printf("%d\n",a>>2);
```

在C语言中，如果数字是无符号的，那么在移动后会补0；若是有符号的，那就是补符号位

6、总结：计算机只会做位运算

### 9、位运算之加减乘除

4+5的运算过程：

1. 4：0000-0100，5：0000-0101
2. 4+5的异或运算：0000-0001

如果不考虑进位的情况下，异或的结果与按位加的结果是一样的

1. 异或类似于按位加，此时必须判断有无进位，如果有进位，就要拿出来进位的值再加
2. 判断是都有进位（只有两个数相加的时候才会有进位），进行与运算。若结果不为0，则说明有进位
3. 判断标准：哪个数字是1，那就说明哪里有进位
4. 异或与按位加是一样的结果，只是拿掉了进位的值
5. 继续异或，将（上次异或出来的结果）与（进位得到的数字左移一位后）继续异或预算
6. 使用与运算，判断是否有进位。若得到结果为0，则说明没有进位
7. 得出最终结果

过程简化后：

1. 异或运算：两数字进行异或运算（结果为C）
2. 与运算：判断两数字进行与运算时是否有进位（结果为D）
3. 异或运算，用C与D进行异或运算，得出最终结果（结果为E）
4. 与运算，用C与D进行与运算，若结果为0，则E为最终结果

4-5的运算过程：

1. 4-5=4+（-5）
2. 异或运算：0000-0100 异或 1111-1011=1111-1111
3. 与运算：判断是否有进位：0000-0100与1111-1011=0000-0000
4. 说明第二步的运算结果就是最终结果，1111-1111：FF，-1

乘法的运算过程：\
&#x20;X\*Y的本质就是加法：Y个X相加

除法的运算过程： \
X/Y的本质就是减法：X能减去多少个Y

### 10、汇编学习环境搭建

1、学汇编不是为了写代码

学汇编的目的：了解程序的运行机制，汇编是高手的必经之路

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDndiW8VNfA8m_USO_b%2F-MDndx4_zPH6Zm9hInAI%2Fimage.png?alt=media\&token=936b2c08-734a-407a-bf2d-fbc249742f4f)

* 正常应用：需要明白C语言等于汇编的对应关系
* 安全：做外挂以及反外挂等，需要了解汇编与二进制的关系。PE与硬编码也需要了解

课堂讲的是32位的汇编，不是win32汇编。\
笔记程度：可看懂普通的应用程序

若想研究擦做系统之类的，需要了解保护模式等相关内容

2、配置汇编的学习环境

1. DTDEBUG下载
2. 配置路径

当想使用OD编写汇编代码时，可随便拖拽一个EXE文件进去，可看到如下页面

![OD的界面](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDndiW8VNfA8m_USO_b%2F-MDnhEZvahDWZlB-gean%2Fimage.png?alt=media\&token=a45d76b7-e3fd-472c-9069-9dbdde4bfab9)

当左上角显示黄色时，说明程序已暂停，此时可双击右面的汇编代码并打开窗口，并在新开的窗口中编写汇编代码

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDndiW8VNfA8m_USO_b%2F-MDnhXNMZ1vSbJvZDDyN%2Fimage.png?alt=media\&token=bdf67d1d-d8b4-4f2f-bd7a-5def23ad794e)

窗口名称：从左往右依次为：反汇编窗口，寄存器，内存窗口与堆栈

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDndiW8VNfA8m_USO_b%2F-MDniGKyPc0St-p3y37A%2Fimage.png?alt=media\&token=1b9b99cd-abc3-4cbd-bb5b-a68e17e295e3)

### 11、通用寄存器

1、寄存器

存储数据：\
CPU>内存>硬盘\
32位CPU：8  16  32\
64位CPU：8  16  32  64

寄存器：CPU用来存储数据的地方\
若是32位CPU，有提供容器有3种类型，为8位16位，32位\
若是64位CPU，有提供容器有4种类型，为8位16位，32位，64位

学习32位汇编的理由：

1. 64位CPU与32位CPU并没有实际的变化，只是增加了新的寄存器，汇编指令都是一样的。若掌握了32位汇编，可以直接看懂64位汇编
2. 绝大多数程序都是32位的

2、通用寄存器

32位通用寄存器：\
在32位寄存器中，大多数寄存器有特殊用途\
在32位的寄存器中，存储的数据不能超过32位，也就是不能超过32个0和1，否则多余的部分会被丢弃

| 名称  | 编号 | 数据存储范围         |
| --- | -- | -------------- |
| EAX | 0  | 0 - 0xFFFFFFFF |
| ECX | 1  | 0 - 0xFFFFFFFF |
| EDX | 2  | 0 - 0xFFFFFFFF |
| EBX | 3  | 0 - 0xFFFFFFFF |
| ESP | 4  | 0 - 0xFFFFFFFF |
| EBP | 5  | 0 - 0xFFFFFFFF |
| ESI | 6  | 0 - 0xFFFFFFFF |
| EDI | 7  | 0 - 0xFFFFFFFF |

不同位数的通用寄存器

| 32位 | 16位 | 8位 |
| --- | --- | -- |
| EAX | AX  | AL |
| ECX | CX  | CL |
| EDX | DX  | DL |
| EBX | BX  | BL |
| ESP | SP  | AH |
| EBP | BP  | CH |
| ESI | SI  | DH |
| EDI | DI  | BH |

其中，L代表低八位，H代表高八位

2、MOV指令

作用：移动数据

汇编可理解为：寄存器与寄存器之间，寄存器与内存之间数据的来回流动\
想学好汇编需要记住的关键词：寄存器，内存，指令

1. 立即数到寄存器
2. 寄存器到寄存器

```
mov eax,1    #向eax存入值1
mov ecx,2    #向ecx存入值2
```

若想执行语句，可点击F8，执行后，寄存器的语句会变成红色

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDniwwvLMwMCACkEDXq%2F-MDnmgEKls-NlaQA-_H5%2Fimage.png?alt=media\&token=11f89727-dba6-4c5d-b5d2-3853694f4070)

也可以将寄存器中的值传到另一个寄存器中，例：

```
mov edx,eax    #将eax的值传到edx中
```

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDniwwvLMwMCACkEDXq%2F-MDnnQ2BjqJ2gGdPogyX%2Fimage.png?alt=media\&token=09c181a5-f421-49d5-bb04-ff2f3a302e25)

其中，因为eax中的值为1，所以edx的值也是1

![16位寄存器为32位的一半](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDniwwvLMwMCACkEDXq%2F-MDnrLPgBURzUGiIgdv9%2Fimage.png?alt=media\&token=74087538-7888-4d7d-8022-2213f4515de5)

八位寄存器：

![H高八位，L低八位](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDniwwvLMwMCACkEDXq%2F-MDnsQLgeWSY41ZIN9pz%2Fimage.png?alt=media\&token=94271034-77a8-41d7-a387-4196a0774e02)

注意：寄存器之间的数值移动，需要位数相同，若位数不同，会报错，不符合语法

### 12、内存

当存储数据足够多的时候，可将数据存储到内存中

内存：并不是内存条

1、每个应用程序都会有自己独立的4GB内存空间

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrAQ0Q3fO1DG2eSqy6%2Fimage.png?alt=media\&token=513b3378-9114-497c-b1f0-48bc5e4c999c)

其中，每个进程的4GB内存空间并不是真正的物理内存，是假的\
当进行读写操作时，会将进程中额内存映射到物理内存中\
物理内存与内存条之间，还有一层映射

在编程过程中，提到的内存，往往指的是4GB的虚拟内存

1Byte=8BIT    1KB=1024Byte   1MB=1024KB 1GB=1024MB 1TB=1024GB 1PB=1024TB

2、内存地址

1. 内存太大没办法起名字，所以只能用编号当我们想想内存中存储数据时，或者从内存中读取数据时，必须用到这个编号，就像写信必须要写收信人一样
2. 这个编号又叫内存地址（32位，前面的0可以省略）

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrDAAA6dIQpYRXJyDw%2Fimage.png?alt=media\&token=8754cbf5-590b-453f-8aee-19c17f92f658)

对于编程人员来讲，内存与寄存器都是用来存储数据的容器，故内存太大了，就用编号代替

其中：

1. \[0x00000000]称为内存地址，为内存块，是8位一字节
2. 在读和写的时候，必须使用内存地址
3. 内存地址有32位，如果转换成16进制的话，就是8位
4. 因为地址宽度是32位，宽度决定了能查找的最大的范围就是4GB，值最大为100000000

计算过程：

1. 16进制最大寻址范围是FFFF-FFFF，加一后为10000-0000
2. 因为每个字节是8位，乘以8就是1-0000-0000
3. 转换成10进制，得到数字：34359738368
4. 除以8以后得出结果为：4294967296
5. 除以1024后，得出结果为：4194304（能找到的KB的数量）
6. 除以1024后，得出结果为：4096（能找到的MB的数量）
7. 除以1024后，得出结果为：4（能找到的GB的数量）

所以，每个进程都有自己的4GB的内存空间

注意：

1. 内存必须有地址，这个地址的宽度是32位的
2. 每个地址对应的内存有一个字节8位，8个0和1

3、MOV指令

1. 立即数到内存
2. 寄存器到内存
3. 内存到寄存器

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrHSUHE4ON1LnsWdZ-%2Fimage.png?alt=media\&token=989b841a-1cb6-4c02-89a1-26eb40455de3)

```
mov byte ptr ds:[],1
```

语句含义：将1写到内存中，写到1个字节中\
ptr ds:\[] 为地址编号，方括号中的内容不可以随便写，必须是已经申请了的地址<br>

![红色方框中即为已申请的地址](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrIPc0EMfkJZxgZSsD%2Fimage.png?alt=media\&token=1bd01c58-11bf-4c3c-9b1c-554f32f5835c)

填入地址后，点击确定即可

```
mov byte ptr ds:[18FFC4],1
```

![效果图](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrIrxIh8wVXWKaRbf4%2Fimage.png?alt=media\&token=e1af903e-1957-4ef0-a7af-091254ff393c)

其中，宽度为8，点击F8后：

![内存内写入数据](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrLg_4xFLpr3a5Yyp0%2Fimage.png?alt=media\&token=3370e71f-4306-4a3c-9b4d-2e699d87afe7)

注意：向内存中写数据的时候，一定要告诉他宽度是多少

```
mov dword ptr ds:[12FFC4],12345678
```

![写入了四个字节的数据](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrMa0ocGSrKGZf5cZW%2Fimage.png?alt=media\&token=3fbbdcc4-11a9-4b64-92a7-a60c25fd2da1)

```
mov dword ptr ds:[12FFC4],ecx
```

![寄存器到内存](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDr9scIxOpDKJ_C76XS%2F-MDrNagOY00HjPbKME-R%2Fimage.png?alt=media\&token=1567b79f-4202-4845-a484-3e4b69bbb7ce)

其中：\
DWORD代表要写的内存有多大，数据宽度是多少\
ptr ds:\[]是固定写法\
\[]中的内容，就是地址，也可称为编号\
每一个编号对应的是一个字节

编号是连续使用的

可以将立即数写到内存中，也可以将寄存器写到内存中，但前提是：宽度必须是一样的

注意：\
在使用MOV指令的时候，要保证两边的宽度是一样的

将内存中的值写入寄存器中：

```
mov ecx,dword ptr ds:[12FFC4]
```

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDrONuxNDJS6jOFslfG%2F-MDrPwqZ17xTUnr_fBrJ%2Fimage.png?alt=media\&token=63cf7c49-6345-4009-baf3-1c765b2a8b30)

在汇编中，就大多数指令是不允许从内存到内存的，其中包括MOV指令；必须经过寄存器；也不能从内存到立即数。立即数不是容器，只能往别的东西里放

涉及代码：

```c
#include "stdafx.h"
#include <stdlib.h>

int x = 1;//全局变量
int main(int argc,char* argv[])
{
    x = 2;
    
    int y = 3;//局部变量
    
    int z[] = {0};
    for(int i=0;i<10;i++)
    {
        z[i] = 1;
    }

}
```

内存的五种表示形式：

1. 立即数：
   1. 读取内存的值：MOV EAX,DWORD PTR DS:\[13FFC4]
   2. 向内存中写入数据：MOV DWORD PTR DS:\[13FFC4],EAX
2. \[reg] reg代表寄存器，可以是8个寄存器中的任意一个
   1. 读取内存的值：MOV EAX,13FFD0  ;   MOV EAX,DWORD PTR DS:\[ECX]
   2. 向内存中写入数据：MOV EDX,13FFD8  ;  MOV DWORD PTR DS:\[DEX],87654321
3. \[reg+立即数]
   1. 读取内存的值：mov ecx,13ffd0  ;   mov eax,dword ptr ds:\[ecx+4]
   2. 向内存中写入数据：mov edx,13FFD8  ;  MOV DWORD PTR DS:\[EDX+0xC],87654321
4. \[reg+reg\*{1,2,4,8}] #在高级语言中对数组赋值，最终生成的汇编语言就是这样的\
   八个32位的通用寄存器加上八个32位的通用寄存器乘以1或2或4或8
   1. 读取内存的值：MOV EAX,13FFC4  ；  MOV ECX,2  ;    MOV EDX,DWORD PTR DS:\[EAX+ECX\*4]
   2. 向内存中写入数据：MOV EAX,13FFC4  ;  MOV ECX,2  ;  MOV DWORD PTR DS:\[EAX+ECX\*4],87654321
5. \[reg+reg\*{1,2,4,8}+立即数] #&#x20;
   1. 读取内存的值：MOV EAX,12FFC4  ;  MOV ECX,2  ;  MOV EDX,DWORD PTR DS:\[EAX+ECX\*4+4]
   2. 向内存中写入数据：MOV EAX,13FFC4  ;  MOV ECX,2  ;  MOV DWORD PTR DS:\[EAX+ECX\*4+4],87654321

学习五种形式的作用：看得懂各式编译器反编译出来的汇编代码

### 13、数据的存储模式

1、存储模式

```
mov byte ptr ds:[0x00000000],0x1A
mov byte ptr ds:[0x00000000],0x1A2C
mov byte ptr ds:[0x00000000],0x1A2C3E4F
```

大端模式：数据高位在低位，数据低位在高位\
小端模式：数据低位在低位，数据高位在高位

![](https://172932098-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MC0hWgbNjaxH4i6ny5D%2F-MDrONuxNDJS6jOFslfG%2F-MDrf0n30g4gpbVZSY_G%2Fimage.png?alt=media\&token=c24eaa8a-3e79-4712-a4c8-83afc550dd72)

2、3、4、

### 14、

### 15、

### 16、

### 17、

### 18、

### 19、

### 20、

### 21、

### 22、

### 23、

### 24、

### 25、

### 26、
