Keep Learning

伪程序员记录点滴

汇编语言学习

本书主要记录的在学习王爽编著的《汇编语言》中的一些记录。

第二章 寄存器(CPU原理)

8086中内存地址的访问是由基地址加上偏移地址组成的物理地址,而这个基地址主要是由段寄存器提供的,在8086中有4个段寄存器,分别是CS,DS,SS和ES。
CS为代码段寄存器,IP为指令指针寄存器,在8086机中,任意时刻,CPU将CS:IP指向的内容当做指令执行。
8086CPU的工作过程如下所示:

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

在8086CPU加电启动或复位后,CSIP被设置为CS=F000H,IP=FFFFH
CPU只认定由CS:IP指向内存单元中的内容为指令。

第三章 寄存器(内存访问)

当CPU要读写一个内存单元时,必须指定内存单元的段地址与偏移地址。在8086CPU中,使用的是DS来指定段地址,当将段地址传送进入DS寄存器时,必须再依靠另外一个寄存器来将该数值传送进入到DS中,不支持直接将数据传送到DS寄存器中。比如想要从内存单元10000H中读取数据到al中,可以采用如下操作:

1
2
3
mov bx, 1000H
mov ds, bx
mov al, [0]

注意上面代码中[0]这个部分是不可缺少的,表示的是一个内存偏移单元而不是一个数。
8086CPU的入栈和出栈操作都是以字为单位的。在任意时刻,SS:SP指向栈顶元素,栈的段地址寄存器为SS,偏移地址寄存器为SP

第四章 第一个程序

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:codesg
codesg segment
start:  mov ax, 0123H
        mov bx, 0456H
        add ax, bx
        add ax, ax

        mov ax, 4c00H
        int 21H

codesg ends
end

汇编语言中有两种类型的指令,分别为伪指令汇编指令segment和ends是一对成对使用的伪指令,用来定义一个段。一个有意义的汇编程序至少有一个段,这个段用来存储程序。end是指定程序结束的标记。assume用于假设某个寄存器与segment ends指定的名称相关联。

第五章 [bx]和loop指令

寄存器中的内容也可作为偏移指令,在使用loop时,每次执行完一次之后,寄存器CX的值都将会减1,因此可以将循环次数放入到CX寄存器中,然后再使用loop来实现循环操作。

第六章 包含多个段的程序

这章节主要介绍程序中可以有多个段,比如代码段、数据段和栈等,整个代码的架构可以使用下面的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
assume cs:code, ds:date, ss:stack
date segment
    dw 0123H, 0234H, 0123H
date ends
stack segment
    dw 0, 0, 0,0
stack ends
code segment
start:  code here
        "
        "
        "
code ends
end start

第七章 更灵活的定位内存地址的方法

这章节主要介绍的是内存寻址的方式,增加了bx寄存器寻址的方式内容,同时引入了SIDI这两个寄存器的寻址方式,其中SIDI这两个提供的方式和bx相似,但是这两个寄存器不能分成两个8位寄存器。
总共的寻址方式可以总结为如下几种:

  1. [idata]用一个常量表示地址用于直接定位一个内存单元;
  2. [bx]用一个变量表示内存地址,用于间接定位一个内存单元;
  3. [bx+idata]用一个变量和常量定义一个内存单元;
  4. [bx+si]用两个变量;
  5. [bx+di+idata]用两个变量和一个常量定义。

第八章 数据处理的两个基本问题

这两个基本问题是:

  • 处理的数据在什么地方?
  • 要处理的数据有多长?

对于数据存储在什么地方这个问题,根据书上的例子,摘抄如下:

机器码 汇编指令 指令执行前数据的位置
8E1E0000 mov bx, [0] 内存,ds:0单元
89C3 mov bx, ax CPU内部,ax寄存器
BB0100 mov bx, 1 CPU内部,指令缓冲器

对于数据的长度,可以有下面三种方法:

  • 通过寄存器名指定要处理的数据的尺寸;
  • 在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,其中X在汇编指令中可以为wordbyte
  • 使用其他方法

这章节还介绍了几个其他指令,分别为div 除法指令dd双字节伪指令dup操作符重复指令

第九章 转移指令的原理

可以修改IP,或同时修改CSIP的指令统称为转移指令。
操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得编号的偏移地址。
jmp为无条件转义指令,可以只修改IP,也可以同时修改CS和IP

第十章 call和ret指令

callret指令都是转移指令,它们都修改IP,或同时修改CSIP

第十一章 标志寄存器

这章节主要介绍的是CPU进行操作之后,在标识寄存器中各标志位的含义,其主要作用如下所示:

  1. 用来存储相关指令的某些执行结果;
  2. 用来为CPU执行相关指令提供行为依据;
  3. 用来控制CPU的相关工作方式。

标志寄存器共有16位,其中有意义的为0、2、4、6、7、8、9、10、11这几位,其余的位均没有意义。

第十二章 内中断

中断分为内中断和外中断,其中产生内中断的方式主要有下面几种:

  • 除法错误,比如在div指令产生除法溢出,中断类型码为:0
  • 单步执行,中断类型码为:1;
  • 执行int0指令中断类型码为:4;
  • 执行int指令中断类型码为对应的整形数。

第十三章 int指令

CPU执行int n指令,相当于引发一个n号中断的中断过程,执行过程如下:

  • 取中断类型码n;
  • 标志寄存器入栈,IF=0,TF=0;
  • CS,IP入栈;
  • IP=(n4),(CS)=(n4+2)

BIOS主要包含的内容:

  • 硬件系统的检测和初始化程序;
  • 外部中断和内部中断例程;
  • 用于对硬件设备进行I/O操作的中断例程;
  • 其他和硬件系统相关的中断例程。

第十四章 端口

对端口的操作使用的是inout指令。

第十五章 外中断

CPU通过端口和外部设备进行联系。
一共有两类中断,可屏蔽中断不可屏蔽中断。不可屏蔽中断用的中断号固定为2。