环境搭建

链接:https://pan.baidu.com/s/1LHbEvY6aZ8pG8IbVDyvAsg?pwd=fduy
提取码:fduy

将压缩包中的MASM复制到D盘根目录,然后默认安装dosbox(注意不要修改安装路径)

打开安装好的dosbox

1
mount c d:masm

即将d:masm挂载至c盘

1
c:

进入c盘

1
dir

查看当前路径下文件

1
debug

进入debug汇编环境

1
r

查看寄存器值

1
2
r ax
1234

修改寄存器ax的值

1
d 1000:0

查看1000:0内存中的数据

1
d 0000:0000 f

查看0000:0000内存中的f个数据

1
e 0000:0000 12 15 34 44

修改0000:0000内存中的数据为12 15 34 44

1
2
3
4
a 073f:0100
add bx,ax
mov cx,ax

修改CS:IP指向的指令

1
t

执行CS:IP处的一条指令

1
u 073f:0100

将073f:0100处机器码指令翻译为汇编指令

物理地址

CPU访问内存单元时需要给出内存单元地址,每个内存单元有个唯一的地址,称作物理地址

8086地址总线为20,运算器一次最多处理16位的数据,因此8086采用两个16位 的地址(段地址、偏移地址),来合成一个20位的物理地址

物理地址 = 段地址 * 16 + 偏移地址

注意,内存并没有分段,段的划分来自cpu

偏移地址16位,所以一个段的长度最多64K

不同的段地址和偏移地址可以形成同一个物理地址

四个段寄存器

代码段寄存器CS、数据的寄存器DS、栈段寄存器SS、附加段寄存器ES

8086寄存器

8086 CPU 中寄存器总共为 14 个,且均为 16 位。

即 AX,BX,CX,DX,SP,BP,SI,DI,IP,FLAG,CS,DS,SS,ES 共 14 个

通用寄存器

AX,BX,CX,DX称作为数据寄存器:

AX (Accumulator):累加寄存器,也称之为累加器;

BX (Base):基地址寄存器;

CX (Count):计数器寄存器;

DX (Data):数据寄存器;

可拆分为H, L两个8位寄存器

段寄存器

CS (Code Segment):代码段寄存器;

DS (Data Segment):数据段寄存器;

SS (Stack Segment):堆栈段寄存器;

ES (Extra Segment):附加段寄存器;

SP和BP又称作为指针寄存器

SP (Stack Pointer):堆栈指针寄存器;

BP (Base Pointer):基指针寄存器;

SI和DI又称作为变址寄存器

SI (Source Index):源变址寄存器;

DI (Destination Index):目的变址寄存器;

控制寄存器

IP (Instruction Pointer):指令指针寄存器;

FLAG:标志寄存器;

寄存器组合

CS:IP 指向当前指令

SS:SP 指向栈顶元素

指令

mov指令

  • mov ax,12 将16进制的12移至ax寄存器
  • mov bx,ax 将ax寄存器的值赋给bx
  • mov ch,10 将16进制的10移至cx寄存器高8位
  • mov ch,al 将ax低8位移至cx高8位

mov ds,10, mov cs,4 是错误的,不可以将立即数赋给段寄存器,需要先把立即数赋给通用寄存器,再将通用寄存器赋给段寄存器

add指令

  • add ax,10 将16进制的10累加在ax
  • add ax,bx

mul指令

  • mov al,64

    mov bl,a

    mul bl 计算16进制64*A并存在ax中

  • mov ax,64

    mov bx,2710

    mul bx 计算16进制64*2710并存在dx ax中

div指令

  • mov ax,2710

    mov bl,64

    div bl 计算16进制2710/64并存在al中(ah存余数)

  • mov dx,f
    mov ax,4240

    mov bx,2710

    div bx 计算16进制f4240/2710并存在ax中(dx存余数)

AX ÷ BL = AL······AH

DX-AX ÷ BX = AX······DX

and,or指令

  • mov al,63(01100011B)

    and al,3b(00111011B) 结果al=23(00100011B)

shl,shr指令

  • mov al,48

    shl al,1 al左移1位(舍高位,右补0)

inc,dec指令

  • inc ax ax自增

jmp指令

  • jmp 2AE3:3 修改cs为2AE3,修改ip为3
  • jmp ax 仅修改ip为ax寄存器的值

内存中字的存储

8086cpu,16位作为一个字,存储在一个16位的寄存器中,高8位放高字节,低8位放低字节;存储在两个8位的内存单元中,高8位放高地址,低8位放低地址

cpu从内存中读取数据

将1000:0读入al

1
2
3
4
5
mov bx, 1000H

mov ds, bx

mov al, [0]

将al写入1000:0

1
2
3
4
5
mov bx, 1000:0

mov ds, bx

mov [0], al

注意,mov ds, 1000H是错误的,不能给ds寄存器立即数,必须通过一个通用寄存器中转

8086可以将一段内存当作栈使用
ss为栈段寄存器,sp为栈顶指针寄存器,任何时刻ss:sp指向栈顶元素

1
2
3
4
5
6
7
8
9
10
11
12
13
mov ax, 1000H

mov ss, ax

mov sp, 0010H

mov ax, 001AH

mov bx, 001BH

push ax

push bx

栈越界问题,栈满再push,栈空再pop,都会发生越界问题,但是汇编不保证不会越界,由程序员自己注意越界问题