汇编入门笔记(三)

0x00:引言

汇编入门文章: http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html。

汇编详细教程: http://c.biancheng.net/asm/。

推荐书籍: 《汇编语言》,《x86汇编语言:从实模式到保护模式》。

小甲鱼《汇编语言》配套视频: https://www.bilibili.com/video/BV1Rs411c7HG?share_source=copy_web。

《汇编语言》配套笔记: https://blog.csdn.net/qq_39654127/article/details/88698911。

检测点答案: https://wenku.baidu.com/view/4ca88c2fad1ffc4ffe4733687e21af45b307fe84.html。

0x01:汇编的来历

最早的时候,编写程序就是手写二进制指令,然后通过各种开关输入计算机,比如要做加法了,就按一下加法开关。后来,发明了纸带打孔机,通过在纸带上打孔,将二进制指令自动输入计算机。

为了解决二进制指令的可读性问题,工程师将那些指令写成了八进制。二进制转八进制是轻而易举的,但是八进制的可读性也不行。很自然地,最后还是用文字表达,加法指令写成 ADD。内存地址也不再直接引用,而是用标签表示。

这样的话,就多出一个步骤,要把这些文字指令翻译成二进制,这个步骤就称为 assembling,完成这个步骤的程序就叫做 assembler。它处理的文本,自然就叫做 aseembly code。标准化以后,称为 assembly language,缩写为 asm,中文译为汇编语言。

汇编语言由3类指令组成。

  • 汇编指令
  • 伪指令:没有对应的机器码,由编译器执行,计算机并不执行
  • 其他符号:如+、-、*、/等,由编译器识别,没有对应的机器码。

编译器:够将汇编指令转换成机器指令的翻译程序每一种CPU都有自己的汇编指令集。

0x02:寄存器

本系列汇编教程以8086CPU为基础。

寄存器组成(8086CPU):

8086CPU有14个寄存器:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW,都是16位。

通用寄存器:

通用寄存器:通常用来存放一般性的数据,有AX、BX、CX、DX,它们可分为两个可独立使用的8位寄存器

16位 8高位 8低位
AX AH AL
BX BH BL
CX CH CL
DX DH DL

在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的。

image-20210926151228938

字(word)在寄存器中的存储:8086CPU是16位CPU,一个字分高、低位两个字节。

image-20210926151559682

image-20210930105426394

0x03:几条汇编指令

image-20210926152204291

以上汇编指令的逻辑顺序都是从右往左的,和高级语言的顺序一致。

汇编指令,寄存器的名字不区分大小写!!

mov指令用于将第二个操作数复制到第一个操作数,但是注意不能直接从内存复制到内存。

1
2
add al,93H
mov ah,bl // 注意指令用的16位寄存器还是8位寄存器

进行数据传输或运算时,注意操作对象位数一致!!

image-20210926153514852

0x04:物理地址

image-20210926154041732

什么是16位CPU?

image-20210926154215824

8086CPU给出物理地址的方法:

8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。
8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。
从8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。

8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。

image-20210926154524476

当8086CPU要读写内存时:

  1. CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
  2. 地址加法器将两个16位地址合成为一个20位的物理地址;

地址加法器采用物理地址 = 段地址×16 + 偏移地址的方法用段地址和偏移地址合成物理地址。

例如,8086CPU要访问地址为123C8H的内存单元,1230H左移一位(空出4位)加上00C8H合成123C8H

0x05:段 的概念

内存实际并未分段,而是CPU为了便于管理内存,将它划分为段。

也是因为之前提到的8086CPU的特殊结构,将1MB的物理地址分段更方便16位CPU处理。

一个段的大小不是固定的。

我们可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元,可以用分段的方式来管理内存。

用一个段存放数据,将它定义为“数据段”;

用一个段存放代码,将它定义为“代码段”;

用一个段当作栈,将它定义为“栈段”。

image-20210926160234215

注意:

  • 一个段的起始地址一定是16的倍数;
  • 偏移地址为16位,变化范围为0-FFFFH,所以一个段的长度最大为64KB;
  • CPU可以用不同的段地址和偏移地址形成同一个物理地址。

在8086CPU中,通常用段地址+偏移地址来表示一个实际的内存地址,直接使用物理地址可能不唯一。

0x06:段寄存器

段寄存器:8086CPU有4个段寄存器:CS、DS、SS、ES,提供内存单元的段地址。

1.CS 和 IP

CS为代码段寄存器,IP为指令指针寄存器,

CPU将CS、IP中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,

在任意时刻,CPU从内存[CS]*16 + [IP]单元开始读取一条指令并执行。

通过《汇编语言》第四版 P26 开始的图示,可以从汇编角度体会CPU执行指令的过程。

8086CPU的工作过程简要描述:

  1. 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
  2. IP=IP+所读取指令的长度,从而指向下一条指令;
  3. 执行指令。转到步骤1,重复这个过程。

2.修改 CS、IP 的指令

两种修改指令:

  • jmp 段地址:偏移地址:用指令中给出的段地址修改CS,偏移地址修改IP。如:jmp 2AE3:3
  • jmp 某一合法寄存器:仅修改IP的内容。如:jmp ax。在含义上好似:mov IP,ax
坚持原创技术分享,您的支持将鼓励我继续创作!