汇编语言的关键字
关于《汇编语言》中的关键字,专业名词
一、基础知识
1、什么是机器语言呢? 机器语言就是机器指令的集合。机器指令指的是一列二进制数字。计算机可以将机器指令转变成一列高低电平,以使计算机的电子器件受到驱动,进行运算。
2、什么是计算机呢? 可以执行机器指令,进行运算的机器。
3、 mov ax,bx 表示把寄存器 BX 的内容送到 AX 中。
4、什么是寄存器呢? 寄存器就是 CPU 中可以存储数据的器件,一个 CPU 可以有多个寄存器,AX,BX 只是寄存器的代号。
5、什么是编译器呢? 编译器就是能够将汇编指令转换成机器指令的翻译程序。
6、汇编指令就是机器指令的助记符,同机器指令一一对应。
7、指令和数据在存储器(内存)中存放。 CPU 想要工作,就必须向他提供指令和数据。而指令和数据又存放在存储器(内存)中 。磁盘不同于内存,磁盘上的数据或程序如果不读到内存中,就无法被 CPU 使用。
8、指令和数据只是应用上的概念,在内存和磁盘中,它们是没有区别的,都是二进制信息。
9、电子计算机的最小信息单位是 bit (一个二进制位)。8 bit 组成一个 byte (字节)。 微机存储器的容量是以字节(byte)为最小单位来计算的。
10、CPU 是如何对存储器进行读取的呢? 首先,我们知道存储器的存储单元是有序号的,并且一个计算机中,可以有多个存储器。 CPU 想要进行数据的读写需要与外部器件进行下面 3 类信息的交互
- 存储单元的地址(地址信息)
- 器件的选择,读或写的命令(命令信息)
- 读或写的数据(数据信息)
11、在计算机中专门有连接 CPU 和其他芯片的导线,通常称为总线。根据传送信息的不同分为 3 类,地址总线、控制总线、数据总线。
12、MOV AX,[3] 传送 3 号单元的内容入 AX
13、CPU 通过地址总线来指定存储器单元的。地址总线上能传送多少个不同的信息,CPU 就可以对多少个存储单元进行寻址。
14、CPU 与内存或其他器件之间的数据传送是通过数据总线来进行的。数据总线的宽度决定了 CPU 和外界的数据传送速度。
15、CPU 对外部器件的控制是通过控制总线来进行的。控制总线是一些不同控制线的集合。控制总线的宽度决定了 CPU 对外部器件的控制能力。
16、每一种 CPU 都有自己的汇编指令集。
17、每一个 CPU 芯片都有许多管脚,这些管脚和总线相连。
18、什么是内存地址空间? 一个 CPU 有 10 根地址总线,那么它可以寻址 1024 个内存单元,这 1024 个可以寻到的内存单元就构成这个 CPU 的内存地址空间。
19、CPU 对外部设备都不能直接控制。直接控制这些设备进行工作的是插在扩展插槽上的接口卡。扩展插槽通过总线与 CPU 相连,所以接口卡通过总线同 CPU 相连。 CPU 通过总线向接口卡发送命令,接口卡根据 CPU 的命令控制外设进行工作。
20、从读写属性上可以将存储器分为两类:随机存储器(RAM)和自读存储器(ROM)。
随机存储器可读可写,但必须带电存储,关机后存储的内容丢失。
只读存储器只能读取不能写入,关机之后其中的内容不丢失。
21、从功能和连接上又分为以下几类
- 随机存储器:用于存放供 CPU 使用的绝大部分程序和数据,主随机存储器一般由两个位置上的 RAM 组成,装在主板上 RAM 和插在扩展插槽上的 RAM。
- 装有 BIOS(Basic Input/Oupur System) 的 ROM:BISO 是由主板和各类接口卡(显卡、网卡等)厂商提供的软件系统,可以通过它利用该硬件设备进行最基本的输入输出。在主板和某些接口卡上插有存储相应 BIOS 的 ROM。
- 接口卡上的 RAM:某些接口卡需要对大批量输入输出数据进行暂时存储,其上装有 RAM。最典型的就是显卡上的 RAM。
22、CPU 会将存储器们总的看作成一个由若干存储单元组成的逻辑存储器。这个逻辑存储器就是我们所说的内存地址空间。每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间。CPU 在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据。
二、寄存器
1、CPU 由运算器、控制器、寄存器等器件构成。
- 运算器进行信息处理
- 寄存器进行数据存储
- 控制器控制各种器件进行工作
- 内部总线连接各种器件,在他们之间进行数据的传送
2、8086 有 14 个寄存器 AX BX CX DX SI DI SP BP IP CS SS DS ES PSW
3、8086CPU 的寄存器都是 16 位的,可以存放两个字节。
4、AX BX CX DX 这 4 个寄存器通常用来存放一般性的数据,被称为通用寄存器。
5、为了向上兼容,AX BX CX DX 都可以分为两个独立使用的 8 位寄存器来使用。 AH(高8位) AL(低8位) BH BL CH CL DH DL
6、几条汇编指令 mov ax,18 ax = 18 mov ah,78 ah = 78 add ax,8 ax = ax + 8 mov ax,bx ax = bx add ax,bx ax = ax + bx
7、在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的。
8、CPU 访问内存单元时,要给出内存单元的地址。所有的内存单元构成存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯一的地址称为物理地址。
9、16 位 CPU 表示
- 运算器一次最多可以处理 16 位数据
- 寄存器的最大宽度为 16 位
- 寄存器和运算器之间的通路为 16 位
10、段地址 × 16 + 偏移地址 = 物理地址 的本质含义 CPU 在访问内存时,用一个基础地址(段地址 × 16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。 基础地址 + 偏移地址 = 物理地址
11、段的概念 内存并没有分段,段的划分来自于 CPU。 段地址 SA 和偏移地址 EA 满足 SA × 16 + EA = 物理地址
12、4 个段寄存器 CS DS SS ES
13、CS 和 IP 是 8086CPU 中两个最关键的寄存器,它们指示了 CPU 当前要读取指令的地址。CS 为代码段寄存器,IP 为指令指针寄存器。
14、在任意时刻,设 CS 中的内容为 M ,IP 中的内容为 N,8086CPU 将从内存 M × 16 + N 单元开始,读取一条指令并执行。 8086 机中,任意时刻,CPU 将 CS:IP 指向的内容当作指令执行。
15、8086CPU 的工作过程 (1)从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲器 (2)IP = IP + 所读取指令的长度,从而指向下一条指令 (3)执行指令。转到步骤(1),重复这个过程。
16、CPU 根据什么将内存中的信息看作指令? CPU 将 CS:IP 指向的内存单元中的内容看做指令,因为,在任何时候,CPU 将 CS、IP 中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中渎职指令码。
17、MOV 指令不用用于设置 CS、IP 的值。JMP 指令可以修改 CS、IP 的指令。 同时修改CS、IP 的内容。jmp 段地址:偏移地址 JMP 2000H:0001H “等同于” MOV CS,2000H MOV IP,0001H 仅修改 IP 的内容 jmp 某一合法寄存器 JMP AX “等同于” MOV IP,AX
18、CPU 在加电启动或复位后,CS、IP 被设置为 FFFFH、0000H。 46
19、8086CPU 的工作过程
- 从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲器
- IP 指向下一条指令
- 执行指令。(转到步骤一,重复这个过程)
20、Debug 的使用 (安装教程地址:https://blog.csdn.net/qq_45382733/article/details/112597079) R 查看、改变 CPU 寄存器的内容 r r ax
D 查看内存中的内容 d 端地址:偏移地址 会显示出 128 个内存单元的内容
E 改写内存中的内容 e 端地址:偏移地址 数据 数据 数据 ..... e 1000:0 0 1 2 3 4 5 6 7 8 9
e 端地址:偏移地址 回车 键 debug 程序会显示起始地址和第一单元的原始内容,在 "." 后面输入想要写入 的数据,通过空格键写入内存。通过回车键结束 e 命令。
U 将内存中的机器指令翻译成汇编指令 u 端地址:偏移地址
T 执行一条机器指令
t #指向 CS:IP 所指向的指令
A 以汇编指令的格式在内存中写入一条机器指令
三、寄存器(内存访问)
1、在内存中存储时,由于内存单元是字节单元(一个单元存放一个字节),则一个字要用两个地址连续的内存单元来存放,这个字的低位字节存放在低地址单元中,高位字节存放在高地址单元中。
2、字单元:存放一个字型数据的内存单元,由两个地址连续的内存单元组成。
3、DS 寄存器,通常用来存放要访问数据的段地址 MOV BX,1000H MOV DS,BX MOV AL,[0] 上面的 3 条指令将 10000H(1000:0)中的数据读到 al 中
3、mov 指令
- 将数据直接送入寄存器
- 将一个寄存器中的内容送入另一个寄存器
4、[...] 表示一个内存单元,[] 里面的数据是指偏移地址,段地址会直接去 ds 寄存器中取
5、8086CPU 不支持直接将数据写入段寄存器,想要把数据写入 ds 寄存器,需要先将数据写入一般寄存器(例如 AX)然后 通过 mov ds,ax 命令将数据写入 ds 寄存器
6、mov mov 寄存器,数据 mov ax,8 mov 寄存器,寄存器 mov ax,bx mov 寄存器,内存单元 mox ax,[0] mov 内存单元,寄存器 mov [0],ax mov 段寄存器,寄存器 mov ds,ax mov 寄存器,段寄存器 mov ax,ds
7、[address]表示一个偏移地址为 address 的内存单元
8、mov、add、sub 是具有两个操作对象的指令。jmp 是具有一个操作对象的指令。
9、0000:0010 = 0001:0000
10、栈是一种具有特殊的访问方式的存储空间。它的特殊性在于,最后进入这个空间的数据,最先出去。
11、PUSH入栈、POP出栈 8086CPU 的入栈和出栈都是以字为单位进行的。
12、段寄存器 SS 和寄存器 SP,栈顶的段地址存放在 SS 中,偏移地址存放在 SP 中。在任意时刻,SS:SP 指向栈顶元素。push 指令和 pop 指令执行时,CPU 从 SS 和 SP中得到栈顶的地址。
13、push ax 的执行过程
- SP=SP-2,SS:SP 指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶
- 将 ax 中的内容送入 SS:SP 指向的内存单元处,SS:SP 此时指向新栈顶。
14、pop ax 的执行过程
- 将 SS:SP 指向的内存单元处的数据送入 ax 中
- SP=SP+2,SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶
15、将 ax 寄存器清零
- mov ax,0 ;占 3 个机器码
- sub ax,ax ;占 2 个机器码
16、push、pop 实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据。
17、ds、cs、ip、ss、sp
- 对于数据段,将它的段地址放在 ds 中,用 mov、ad的、sub 等访问内存单元的指令时,CPU 就将我们定义的数据段中的内容当做数据来访问;
- 对于代码段,将它的段地址放在 CS 中,将段中的第一条指令的偏移地址放在 IP 中,这样 CPU 就将执行我们定义的代码段中的指令;
- 对于栈段,将它的段地址放在 SS 中,将栈顶单元的偏移地址放在 SP 中,这样 CPU 在需要进行栈操作的时候,比如 push、pop 指令等,就将我们定义的栈段当作栈空间来用。
18、debug 的 T 命令在执行修改寄存器 SS 的指令时,下一条指令也紧接着被执行。
四、第一个程序
1、一个汇编语言从写出到最终执行的过程
- 编写汇编源程序
- 对源程序进行编译连接(先编译,生成目标文件,再连接,生成可执行文件)
- 执行可执行文件中的程序
2、一个简单的汇编代码
assume cs:abc
abc segment
mov ax,2 add ax,ax add ax,ax
mov ax,4c00h int 21H ; 这两条命令的作用是使程序返回。
abs ends
end
3、一个程序结束后,将 CPU 的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回
4、伪指令:由编译器来执行的指令。
- XXX segment ... XXX ends ; segment 表示开始 ends 表示结束
- end ; end 是一个汇编程序结束的标记。
- assume ;将有特定用途的段和相关的段寄存器关联起来
5、标号 XXX 在 segment 的前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址。
6、汇编程序编译连接过程
- 编译 (1)编写源程序(代码),保存为 xx.asm (2)运行 masm.exe 程序 (3)输入源程序的文件名 (4)输入编译出的目标文件的名称(.obj) (5)按回车,忽略编译器将源程序编译为目标 文件的过程中产生的中间结果(.lst) (6)按回车,不生成交叉引用文件(.crf) cross-refrence (7)此时就生成了中间文件 xxx.obj
- 连接 (1)运行 link.exe 程序 (2)输入目标文件名 (3)输入要生成的可执行文件的名称 (4)按回车,不生成映像文件 (5)输入库文件的名称 (6)此时就生成了可执行文件 xxx.exe
7、连接程序的作用
- 当源程序很大时,可以分开编译,通过连接程序将目标文件连接在一起,生成一个可执行文件
- 程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接在一起,生成一个可执行文件
- 将目标文件处理成可执行文件
8、简洁方式
- 编译过程 masm 1; 在源程序文件后加上分号,可以直接忽略中间文件的生成
- 连接过程 link 1; 在目标文件后加上分号,可直接忽略中间文件的生成
9、可执行程序的调试 debug 1.exe 注意:要带上 .exe
五、[BX] 和 loop 指令
1、[bx] 表示一个内存单元,它的偏移地址在 bx 中,段地址在 ds 中
2、() 中的内存单元的地址为物理地址
- 寄存器名
- 段寄存器名
- 内存单元的物理地址
3、inc bx 等同于 add bx,1 将 bx 中的内容加 1
4、在汇编中,数据不能以字母开头。 0a000h,0a0001h, .... ,0ffffh
5、int 21 命令要通过 p 命令来执行,而不是 t 命令
6、debug 程序的 g 命令 g 0012 表示使 debug 从当前的 CS:IP 指向的指向执行,一直到 (IP)=0012h 为止 0012 可通过 u 命令查看到loop 命令接着的参数
7、debug 程序的 p 命令 p 命令可以循环一次执行完 (cx)=0
8、段前缀 mov ax,ds:[bx] mov ax,cs:[bx] mov ax,ss:[bx] mov ax,es:[bx]
9、一段安全的空间 0:200h - 0:2ffh 一共 256 个字节
六、包含多个段的程序
1、程序获取内存空间的方法有两种
- 加载程序的时候为程序分配(通过在源程序中定义段来进行内存空间的获取)
- 程序在执行的过程中向系统申请
2、dw,define word,定义字型数据。(2 个字节)
3、程序运行的时候,CS 中存放代码段的段地址
4、end 的作用
- 通知编译器程序结束
- 通知编译器程序的入口在什么地方
5、可执行文件中程序执行过程
- 由其他的程序(Debug、command 或其他程序)将可执行文件中的程序加载入内存
- 设置 CS:IP 指向程序的第一条要执行的指令(即程序的入口,根据end关键字可以知道程序的入口是哪里,程序加载之后,会将 CS:IP 指向程序开始的地址),从而使程序得以运行
- 程序运行结束后,返回到加载者
6、在代码段中使用数据 assume cs:code
code segment ... 数据 ... start: ... 代码 ... code ends end start
7、为什么要把数据、栈和代码放到不同段中?
- 把它们放到一个段中使程序显得混乱
- 如果数 据、栈和代码需要的空间超过 64KB,就不能放在一个段中(这个是 8086CPU 的限制,并不是所有的处理器都这样)
七、更灵活的定位内存地址的方法
1、and 和 or 指令
- and mov al,01100011b and al,00111011b
- or mov al,01100011b or al,00111011b
2、关于 ASCII 码 db define bytye
3、以字符形式给出的数据,用单引号(') 括起来。例如 db 'UNIX'
assume cs:code,ds:data
data segment
db 'unIX'
db 'foRK'
data ends
code segment
start:
mov al,'a'
mov bl,'b'
mov ax,4c00h
int 21h
code ends
end start
4、大小写转换的问题
字母转大写 and 11011111B 字母转小写 or 0010000B
assume cs:code,ds:data
data segment
db 'BaSiC'
db 'iNfOrMaTiOn'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov bx,0
mov cx,5
s:
mov al,[bx]
and al,11011111b
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s1:
mov al,[bx]
or al,0010000b
mov [bx],al
inc bx
loop s1
mov ax,4c00h
int 21h
code ends
end start
5、[bx+idata] 表示一个偏移地址为(bx) + idata 内存单元 mov ax,[bx+200] 等同于 (ax) = ((ds)*16 + (bx) +200) 偏移地址为 bx 的数值加上 200,段地址在 ds 中 可以写成下面格式
- mov ax,[bx+200]
- mov ax,200[bx]
- mov ax,[bx].200
6、用[bx+idata]的方式进行数组的处理
7、SI 和 DI si 和 di 不能够分成两个 8 位寄存器来使用
assume cs:code,ds:data
data segment
db 'welcome to masm!'
db '................'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov di,16
mov cx,8
s: mov ax,[si]
mov [di],ax
add si,2
add di,2
loop s
mov ax,4c00h
int 21h
code ends
end start
8、[bx+si] 和 [bx+di]
[bx+si] 表示一个内存单元,他的偏移地址为(bx)+(si) 即 bx 中的数值加上 si 中的数值
mov ax,[bx+si] <==> (ax) = ((ds)*16 + (bx) + (si))
<==> mov ax,[bx][si]
9、[bx+si+idata] 和 [bx+di+idata]
mov ax,[bx+si+idata] <==> (ax) = ((ds)*16 + (bx) + (si) + idata)
mov ax,[bx+200+si]
mov ax,[20o+bx+si]
mov ax,200[bx][si]
mov ax,[bx].200[si]
mov ax,[bx][si].200
10、不同的寻址方式的灵活应用
[idata]用一个常量来表示地址,可用于直接定位一个内存单元[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元[bx+si]用两个变量表示地址[bx+si+idata]用两个变量和一个常量表示地址
八、数据处理的两个基本问题
1、在 8086CPU 中,只有 bx、si、di、bp 四个寄存器可以用在[...]中进行内存单元的寻址。这四个寄存器可以任意组合。只要在[...]中使用
bp,而指令中没有 显性地给出段地址,段地址就默认在 ss 中。
2、汇编中数据位置的表达
- 立即数 idata,直接包含在机器指令中的数据
- 寄存器,指令要处理的数据在寄存器中
- 段地址 SA 和偏移地址 EA,指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出 EA,SA 在某个段寄存器中
3、寻址方式
- [idata]
- [bx]
- [si]
- [di]
- [bp]
- [bx+idata]
- [si+idata]
- [di+idata]
- [bp+idata]
- [bx+si]
- [bx+di]
4、指令要处理的数据有多长
- 通过寄存器名指明要处理的数据的尺寸
- 在没有寄存器名存在的情况下,用操作符 Xptr 指明内存单元的长度
mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
5、综合应用
mov ax,seg
mov ds,ax
mov bx,60h
mov word ptr [bx+0ch],38
mov word ptr [bx+0eh],70
mov si,0
mov byte ptr [bx+10h+si] ,'V'
inc si
mov byte ptr [bx+10h+si] ,'A'
inc si
mov byte ptr [bx+10h+si] ,'X'
struct company{
char cn[3];
char hn[9];
int pm;
int sr;
char cp[3];
};
struct company dec = {"DEC","Ken Plsen",137,40,"PDP"};
main(){
int i;
dec.pm = 38;
dec.sr = dec.sr + 70;
i = 0;
dec.cp[i] = 'V'
i++;
dec.cp[i] = 'A'
i++;
dec.cp[i] = 'X'
return 0;
}
6、div 是除法指令
- 除数:8 或 16 位
- 被除数:默认在 AX 或 DX 和 AX 中。 除数为 8 位 ,被除数在 AX 中,16位 除数为 16 位,被除数在 DX 和 AX 中,32 位,DX 放高 16 位,AX 放低 16 位
- 结果
除数为 8 位,AL 存商,AH 存余数
除数为 16 为,AX 存商,DX 存 余数
div byte ptr ds:[0](al)=(ax)/((ds)*16+0)的商(ah)=(ax)/((ds)*16+0)的余数
7、伪指令dd (double word),定制双字型数据
data segment db 1 ;1 字节 dw 1 ;2 字节 dd 1 ;4 字节 data ends
8、dup 和 db、dw、dd 等数据定义伪指令配合使用的,用来进行数据的重复
db 3 dip (0) <==> db 0,0,0
db 3 dup (0,1,2) <==> db 0,1,2,0,1,2,0,1,2
db 重复的次数 dup (重复的字节型数据)
dw 重复的次数 dup (重复的字型数据)
dd 重复的次数 dup (重复的双字型数据)
九、转移指令的原理
1、可以修改 IP 或同时修改 CS 和 IP 的指令统称为转移指令。
2、转移行为
- 只修改 IP,称为段内转移
- 短转移 -128~127
- 近转移 -32768~32767
- 同时修改 CS 和 IP,称为段间转移
3、转移指令分类
- 无条件转移
- 条件转移
- 循环
- 过程
- 中断
4、操作符 offset ,取得标号的偏移地址。
5、jmp 指令,jmp 为无条件指令,可以只修改 IP,也可以同时修改 CS 和 IP。 (1)转移的目的地址 (2)转移的距离(段间转移、段内短转移、段内近转移)这一点很重要,是转移的距离,并不是转移到标号处
6、“jmp short 标号” 指令所对应的及其码中,并不包含转移的目的地址,而包含的是转移的位移。 复习下 CPU 执行指令的过程
- 从 CS:IP 指向的内存单元读取指令,读取的指令进入指令缓冲区
- (IP)=(IP) + 所读取指令的长度,从而指向下一条指令
- 执行指令。转到步骤1
7、jmp short 标号 => (IP) = (IP) + 8 位位移
jmp near ptr 标号 => (IP) = (IP) + 16 位位移
jmp far ptr 标号 => (CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址
jmp 16位reg => (IP)=(16位reg)
jmp word ptr 内存单元地址(段内转移) => 转移到偏移地址为内存单元地址处存放的数据上 (IP)=(内存单元地址)
jmp dword ptr 内存单元地址(段间转移) => (CS)=(内存单元地址+2) 高地址为段地址 ;(IP)=(内存单元地址) 低地址为偏移地址
位移由编译程序在编译的时候计算出。
8、jxcz 指令为有条件转移指令,所有的有条件指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。 if((cx)=0) jmp short 标号
9、loop 指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移, 而不是目的地址。 (cx)--; if((cx)≠0)jmp short 标号