0%

汇编笔记(一)

1 基础知识

汇编语言产生于机器语言的过于复杂和难以记忆。

汇编指令通过编译器编译为机器码后,计算机才可以理解。

2 寄存器:CPU工作原理

2.1 通用寄存器

16位寄存器可以放两个字节。AX BX CX DX通常被用来存放一般性的数据,被称为通用寄存器。

AX:由低到高填入二进制数,空位补零。

16位寄存器储存的最大数:2^16-1。

存在8位寄存器,为了兼容8位寄存器,一个16位的寄存器可以分为两个独立的8位寄存器使用。AX可以分为AH(high)高地址和AL(low)低地址。

2.2 字在寄存器中的存储

一个字占两个字节,一个字节8位。一个内存单元是8位。

2.3 几条汇编指令

语法:不分大小写。

mov ax,18:将18这个值赋给ax寄存器。 ax = 18

add ax,8:将ax中的数值+8。 ax += 8

add ax,bx:将ax,bx中的内容相加,结果存在ax中。

如果相加的结果大于16位,多出部分会放到别的地方。

2.4 物理地址

cpu访问内存单元时要给出内存单元的地址,所有的内存单元构成的存储空间是一个一维的线性空间。这个唯一的地址称为物理地址。

2.5 16位的cpu

16位cpu具有一下三方面的特点:

  1. 运算器以此作多可以处理16位的数据。

  2. 寄存器的最大宽度是16位。

  3. 寄存器和运算器之间的通路是16位。

    (且cpu位数等于数据总线的条数)

2.6 8086cpu给出物理地址的方法

8086的地址总线位20位,内部位16位,寻址能力并不相同。它采用了一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。

16位段地址 + 16位偏移地址 –> 经过地址加法器 –> 生成20位地址

具体过程:段地址*16(16进制左移一位),在于偏移地址相加,得到20位地址。

生成同一个地址,可能有多种段地址和偏移地址的组合。

2.7

2.8 段的概念

在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址*16定位段的起使地址(基础地址),用偏移地址定位段中的内存单元。

  • 段地址*16必然是16的倍数,所以一个短的起始地址也一定是16的倍数;
  • 偏移地址位16位,16位地址的寻址能力位64K,所以一个段的长度最大为64K。范围为:0~FFFFH。

2000段中的1F60H单元 = 2000:1F60单元。

2.9 段寄存器

CS(code segment) 代码段寄存器:

DS(data segment) 数据段寄存器

SS(stact segment) 栈段寄存器

ES(extra segment) 额外段寄存器

为8086的4个段寄存器。当8086要访问内存时,由这4个段寄存器提供内存的单元的段地址。

2.10 CS和IP

CS(code segment) 代码段寄存器:

  • 指示了cpu当前要读取指令的地址。

    CS为代码段寄存器。

    IP为指令指针寄存器(偏移寄存器)。

  • 步骤:

    1. 从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器(准备执行);
    2. IP = IP + 读取指令的长度,从而指向下一条指令;
    3. 执行指令,回到步骤1,重复。
  • 8086pc工作的简要描述:

    • 在加电启动或复位后,CS和IP被设置为CS=FFFFH,IP=0000H;
    • cpu从内存FFFF0H单元中读取指令执行。
    • FFFF0H端元中的指令是8086开机后执行的第一条指令。

如果说,内存中的一段信息曾被cpu执行过,那么它所在的内存单元必定被CS:IP指向过。

2.11 修改CS IP的指令

程序员可以通过使用jmp指令改变CS IP中的内容控制cpu执行的目标指令。

jmp 2000:2AE3:修改CS和IP。

jmp ax:将ax的值赋给IP,只修改IP的值。

2.12 代码段

可以将长度小于64K的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,这段内存用来存放代码,从而定义了一个代码段。

只有被CS:IP指向的内存单元中的内容才会被cpu认为是指令。用DS会被理解为数据。

要将CS:IP指向代码段的第一条指令。

3 寄存器:内存访问

3.1 内存中字的存储

一个地址单元放一个字节,8位。一个字型数据站两个字节,也就是两个地址单元。

任何两个地址连续的内存单元,n号单元和n+1号单元,可以将它们堪称两个内存单元,也可以看成一个地址为n的字单元中的高位字节单元和低位字节单元。

3.2 DS和[address]

1
2
3
4
# 将字节数据从内存单元送入寄存器
mov bx,1000H;
mov ds,bx;
mov al,[0];

ds中的1000H是段地址,[ ]中是偏移地址。上面三条指令将1000:0中的数据读到al中。

  • 不可以直接给ds段寄存器赋值。
  • 在从内存中取值之前,在ds里设置好段地址,取值时用[ ]写偏移地址。
1
2
3
4
# 将字节数据从寄存器送入内存单元
mov bx,1000H;
mov ds,bx;
mov [0],al;

3.3 字的传送

1
2
3
4
mov bx,1000H;
mov ds,bx;
mov ax,[0]; #1000:0处的字形数据送入ax
mov [0],cx; #cx中的16位数据送到1000:0

3.4 mov、add、sub指令

mov指令的几种形式:

  • mov 寄存器,数据
  • mov 寄存器,寄存器
  • mov 寄存器,内存单元
  • mov 内存单元,寄存器
  • mov 段寄存器,寄存器
  • mov 寄存器,段寄存器

add和sub指令同mov一样,都有两个操作对象。但是它们两个不可以操作段寄存器。因为段寄存器无法进行四则运算。

3.5 数据段

可以根据需要将一组内存单元定义为一个段(可以是代码段、数据段等)。必须是16的倍数。

3.6 栈

栈是一种具有特殊访问方式的数据存储空间。先进后出。

3.7 cpu提供的栈机制

PUSH(入栈)ax:将寄存器ax中的数据送入栈中。

POP(出栈)ax:从栈顶取出数据ax。

cpu如何找到栈顶元素的位置?通过SS:SP找到栈顶元素的地址。

PUSH的过程:SP = SP - 2,然后将数据送入SP指向的内存单元处。

POP的过程:将SP指向位置的数据取出来,然后SP = SP + 2。

空栈时,SP指向最高地址单元的下一个地址。