多读书多实践,勤思考善领悟

汇编语言简明教程

一、基础知识


1、指令

机器指令:CPU能直接识别并执行的二进制编码

汇编指令:汇编指令是机器指令的助记符,同机器指令一一对应。

指令:指令通常由操作码和地址码(操作数)两部分组成

指令集:每种CPU都有自己的汇编指令集。

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

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

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

在内存或磁盘上,指令和数据没有任何区别,都是二进制信息

2、存储器

随机存储器(RAM)在程序的执行过程中可读可写,必须带电存储

只读存储器(ROM)在程序的执行过程中只读,关机数据不丢失

3、总线


1)、总线

总线是连接各个部件的信息传输线,是各个部件共享的传输介质

主板上有核心器件和一些主要器件,这些器件通过总线(地址总线、数据总线、控制总线)相连。这些器件有CPU、存储器、外围芯片组、扩展插槽等。扩展插槽上一般插有RAM内存条和各类接口卡

总线根据位置分类:

  • 片内总线(芯片内部总线)

  • 系统总线(计算机各部件之间的信息传输线)

    根据传送信息的不同,系统总线从逻辑上又分为3类,地址总线、控制总线和数据总线。

CPU要想进行数据的读写,必须和外部器件(标准的说法是芯片)进行以下3类信息的交互。

  1. 地址总线:CPU通过地址总线来指定存储单元

    1根导线可以传送的稳定状态只有两种,高电平或是低电平。用二进制表示就是1或0

    10根地址线即一次可以传输10位,访问存储单元地址为1011,寻址范围为0 ~ (210 - 1)

  2. 数据总线:CPU与内存或其他器件之间的数据传送是通过数据总线来进行的

    8根数据线一次可传送一个8位二进制数据(即一个字节),传送2个字节需要两次;16根数据线一次可传送2个字节(内存对齐核心原理)

  3. 控制总线:CPU对外部器件的控制是通过控制总线来进行的。
    有多少根控制总线,就意味着CPU提供了对外部器件的多少种控制。
    所以,控制总线的宽度决定了CPU对外部器件的控制能力。

2)、CPU对存储器的读写

1、 CPU通过地址线将地址信息3发出。
2、 CPU通过控制线发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据。
3、 存储器将3号单元中的数据8通过数据线送入CPU。写操作与读操作的步骤相似。
联想:在组成原理中用微操作表示:(PC) → MAR; 1 → R; M(MAR) → MDR; …

3)、CPU对外设的控制

CPU对外设都不能直接控制,如显示器、音箱、打印机等。

直接控制这些设备进行工作的是插在扩展插槽上的接口卡。

扩展插槽通过总线和CPU相连,所以接口卡也通过总线同CPU相连。CPU可以直接控制这些接口卡,从而实现CPU对外设的间接控制。

如:CPU无法直接控制显示器,但CPU可以直接控制显卡,从而实现对显示器的间接控制

4)、内存地址空间

CPU将系统中各类存储器看作一个逻辑存储器,这个逻辑存储器就是我们所说的内存地址空间。
对于CPU,所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受CPU寻址能力限制。

每个物理存储器在逻辑存储器中占有一个地址段,即一段地址空间。CPU在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据(对ROM写无效)。

二、寄存器


1、寄存器

CPU由运算器、控制器、寄存器等器件构成,这些器件靠片内总线相连。

运算器进行信息处理;控制器控制各种器件进行工作;寄存器进行信息存储;

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

16位结构CPU具有下面几方面的结构特性。

  • 运算器一次最多可以处理16位的数据;
  • 寄存器的最大宽度为16位;
  • 寄存器和运算器之间的通路为16位。

8086CPU可以一次性处理以下两种尺寸的数据。

  • 字节:记为byte,一个字节由8个bit组成,可以存在8位寄存器中。
  • 字:记为word,一个字由两个字节组成,可以存在一个16位寄存器中(16位CPU)

8086采用小端模式:高地址存放高位字节,低地址存放低位字节。

2、通用寄存器

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

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

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

一个8位寄存器所能存储的数据范围是0 ~ 28-1。

3、8086CPU给出物理地址的方法

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

当8086CPU要读写内存时:

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

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

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

4、段寄存器

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

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

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

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

注意:

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

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

1)、CS和IP

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

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

CPU将CS:IP指向的内容当作指令执行。(即PC)

8086CPU的工作过程简要描述

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

在8086CPU加电启动或复位后(即CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086PC机刚启动时,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。

8086CPU提供转移指令修改CS、IP的内容。

  • jmp 段地址:偏移地址:用指令中给出的段地址修改CS,偏移地址修改IP。如:jmp 2AE3:3
  • jmp 某一合法寄存器:仅修改IP的内容。如:jmp ax。在含义上好似:mov IP,ax

8086CPU不支持将数据直接送入段寄存器的操作,这属于8086CPU硬件设计

2)、DS 和 [address]

DS寄存器:通常用来存放要访问数据的段地址

[address]表示一个偏移地址为address的内存单元,段地址默认放在ds中

通过数据段段地址和偏移地址即可定位内存单元。

1
2
3
4
5
6
7
8
9
10
11
mov bx, 1000H ;8086CPU不支持将数据直接送入段寄存器的操作

mov ds, bx ;ds存放数据段地址

mov [0], al ;将al数据(1字节)存到1000H段的0偏移地址处,即10000H

mov ax, [2] ;将数据段偏移地址2处的一个字(80862字节)存放到ax寄存器

add cx, [4] ;将偏移地址4处的一个字数据加上cx寄存器数据放到cx寄存器

sub dx, [6] ;dx寄存器数据减去数据段偏移地址6处的字数据存到dx

3)、SS 和 SP

在基于8086CPU编程的时候,可以将一段内存当作栈来使用。

栈段寄存器SS,存放段地址,SP寄存器存放偏移地址,任意时刻,SS:SP指向栈顶元素

8086CPU中,入栈时,栈顶从高地址向低地址方向增长。

push ax表示将寄存器ax中的数据送入栈中,由两步完成。

  1. SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;
  2. 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。

pop ax表示从栈顶取出数据送入ax,由以下两步完成。

  1. 将SS:SP指向的内存单元处的数据送入ax中;
  2. SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

实验

  1. 将10000H~1000FH这段空间当作栈,初始状态栈是空的;
  2. 设置AX=001AH,BX=001BH;
  3. 将AX、BX中的数据入栈;
  4. 然后将AX、BX清零;
  5. 从栈中恢复AX、BX原来的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mov ax, 1000H 
mov ss, ax
mov sp, 0010H ;初始化栈顶
mov ax, 001AH
mov bx, 001BH

push ax
push bx ;ax、bx入栈

sub ax, ax ;将ax清零,也可以用mov ax,0,
;sub ax,ax的机器码为2个字节,
;mov ax,0的机器码为3个字节。

sub bx, bx

pop bx ;从栈中恢复ax、bx原来的数据
pop ax ;

四、[bx] 和 loop指令


1、[bx] 和 loop指令

[bx] 的含义:[bx]同样表示一个内存单元,它的偏移地址在bx中,段地址默认在ds中

loop指令的格式是:loop 标号,CPU执行loop指令的时候,要进行两步操作,

  1. (cx) = (cx) - 1;
  2. 判断 cx 中的值,不为零则转至标号处执行程序,如果为零则向下执行。

例如:计算212

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code 

code segment
mov ax, 2

mov cx, 11 ;循环次数
s: add ax, ax
loop s ;在汇编语言中,标号代表一个地址,标号s实际上标识了一个地址,
;这个地址处有一条指令:add ax,ax。
;执行loop s时,首先要将(cx)减1,然后若(cx)不为0,则向前
;转至s处执行add ax,ax。所以,可以利用cx来控制add ax,ax的执行次数。

mov ax,4c00h
int 21h
code ends
end

loop 和 [bx] 的联合应用

计算ffff:0 ~ ffff:b单元中的数据的和,结果存储在dx中

问题分析:

  1. 这些内存单元都是字节型数据范围0 ~ 255 ,12个字节数据和不会超过65535,dx可以存下
  2. 对于8位数据不能直接加到 dx

解决方案:

用一个16位寄存器来做中介。将内存单元中的8位数据赋值到一个16位寄存器a中,再将ax中的数据加到dx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
assume cs:code 

code segment
mov ax, 0ffffh ;在汇编源程序中,数据不能以字母开头,所以要在前面加0。
mov ds, ax
mov bx, 0 ;初始化ds:bx指向ffff:0
mov dx, 0 ;初始化累加寄存器dx,(dx)= 0

mov cx, 12 ;初始化循环计数寄存器cx,(cx)= 12
s: mov al, [bx]
mov ah, 0
add dx, ax ;间接向dx中加上((ds)* 16 +(bx))单元的数值
inc bx ;ds:bx指向下一个单元
loop s

mov ax, 4c00h
int 21h
code ends
end

2、段前缀

1
2
3
4
5
6
mov ax, ds:[bx]
mov ax, cs:[bx]
mov ax, ss:[bx]
mov ax, es:[bx]
mov ax, ss:[0]
mov ax, cs:[0]

这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址
的“ds:”,“cs:”,“ss:”,“es:”,在汇编语言中称为段前缀。

段前缀的使用

将内存ffff:0 ~ ffff:b单元中的数据复制到0:200 ~ 0:20b单元中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
assume cs:code 

code segment
mov ax, 0ffffh
mov ds, ax ;(ds)= 0ffffh
mov ax, 0020h
mov es, ax ;(es)= 0020h 0:200 等效于 0020:0
mov bx, 0 ;(bx)= 0,此时ds:bx指向ffff:0,es:bx指向0020:0

mov cx12 ;(cx)=12,循环12次
s: mov dl,[bx] ;(d1)=((ds)* 16+(bx)),将ffff:bx中的字节数据送入dl
mov es:[bx],dl ;((es)*16+(bx))=(d1),将dl中的数据送入0020:bx
inc bx ;(bx)=(bx)+1
loop s

mov ax4c00h
int 21h
code ends
end

五、包含多个段的程序

程序中对段名的引用,将被编译器处理为一个表示段地址的数值。

1
2
3
4
5
6
mov ax, data 

mov ds, ax

mov bx, ds:[6]
12345

在代码段中使用数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
;计算 8 个数据的和存到 ax 寄存器
assume cs:code

code segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h ;define word 定义8个字形数据

start: mov bx, 0 ;标号start
mov ax, 0

mov cx, 8
s: add ax, cs:[bx]
add bx, 2
loop s

mov ax, 4c00h
int 21h
code ends
end start ;end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方
;用end指令指明了程序的入口在标号start处,也就是说,“mov bx,0”是程序的第一条指令。

在代码段中使用栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
;利用栈,将程序中定义的数据逆序存放。
assume cs:codesg

codesg segment
dw 0123h0456h0789h0abch0defh0fedh0cbah0987h ; 0-15单元
dw 0000000000000000 ; 16-47单元作为栈使用

start: mov ax, cs
mov ss, ax
mov sp, 30h ;将设置栈顶ss:sp指向栈底cs:30。 30h = 48d
mov bx, 0

mov cx, 8
s: push cs:[bx]
add bx, 2
loop s ;以上将代码段0~15单元中的8个字型数据依次入栈

mov bx, 0

mov cx, 8
s0: pop cs:[bx]
add bx2
loop s0 ;以上依次出栈8个字型数据到代码段0~15单元中

mov ax4c00h
int 21h
codesg ends
end start ;指明程序的入口在start处

将数据、代码、栈放入不同的段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
assume cs:code,ds:data,ss:stack 

data segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h ;0-15单元
data ends

stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;0-31单元
stack ends

code segment
start: mov ax, stack;将名称为“stack”的段的段地址送入ax
mov ss, ax
mov sp, 20h ;设置栈顶ss:sp指向stack:20。 20h = 32d

mov ax, data ;将名称为“data”的段的段地址送入ax
mov ds, ax ;ds指向data段

mov bx, 0 ;ds:bx指向data段中的第一个单元

mov cx, 8
s: push [bx]
add bx, 2
loop s ;以上将data段中的0~15单元中的8个字型数据依次入栈

mov bx, 0

mov cx, 8
s0: pop [bx]
add bx, 2
loop s0 ;以上依次出栈8个字型数据到data段的0~15单元中

mov ax, 4c00h
int 21h
code ends
end start
;“end start”说明了程序的入口,这个入口将被写入可执行文件的描述信息,
;可执行文件中的程序被加载入内存后,CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令

关于可执行文件结构与程序入口的详细描述参考:PE文件结构

六、更灵活的定位内存地址的方法


1、and 和 or

and指令:逻辑与指令,按位进行与运算。

1
2
mov al, 01100011B`
`and al, 00111011B

执行后:al=00100011B即都为1才为1

or指令:逻辑或指令,按位进行或运算。

mov al, 01100011B
or al, 00111011B
执行后:al=01111011B 即只要有一个为1就为1

关于ASCII码
世界上有很多编码方案,有一种方案叫做ASCII编码,是在计算机系统中通常被采用的。简单地说,所谓编码方案,就是一套规则,它约定了用什么样的信息来表示现实对象。比如说,在ASCII编码方案中,用61H表示“a”,62H表示“b”。一种规则需要人们遵守才有意义。

在文本编辑过程中,我们按一下键盘的a键,就会在屏幕上看到“a”。我们按下键盘的a键,这个按键的信息被送入计算机,计算机用ASCII码的规则对其进行编码,将其转化为61H存储在内存的指定空间中;文本编辑软件从内存中取出61H,将其送到显卡上的显存中;工作在文本模式下的显卡,用ASCII码的规则解释显存中的内容,
61H被当作字符“a”,显卡驱动显示器,将字符“a”的图像画在屏幕上。我们可以看到,显卡在处理文本信息的时候,是按照ASCII码的规则进行的。这也就是说,如果我们要想在显示器上看到“a”,就要给显卡提供“a”的ASCIⅡ码,61H。如何提供?当然是写入显存中。

以字符形式给出的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
assume cs:code,ds:data 

data segment
db 'unIx' ;相当于“db 75H,6EH,49H,58H”
db 'foRK'
data ends

code segment
start: mov al, 'a' ;相当于“mov al, 61H”,“a”的ASCI码为61H;
mov b1, 'b'

mov ax, 4c00h
int 21h
code ends
end start

大小写转换的问题

小写字母的ASCII码值比大写字母的ASCII码值大20H

大写字母ASCII码的第5位为0,小写字母的第5位为1(其他一致)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
assume cs:codesg,ds:datasg 

datasg segment
db 'BaSiC'
db 'iNfOrMaTion'
datasg end

codesg segment
start: mov ax, datasg
mov ds, ax ;设置ds 指向 datasg段

mov bx, 0 ;设置(bx)=0,ds:bx指向’BaSic’的第一个字母

mov cx, 5 ;设置循环次数5,因为’Basic'有5个字母
s: mov al, [bx] ;将ASCII码从ds:bx所指向的单元中取出
and al, 11011111B;将al中的ASCII码的第5位置为0,变为大写字母
mov [bx], al ;将转变后的ASCII码写回原单元
inc bx ;(bx)加1,ds:bx指向下一个字母
loop s

mov bx, 5 ;设置(bx)=5,ds:bx指向,iNfOrMaTion'的第一个字母

mov cx, 11 ;设置循环次数11,因为‘iNfOrMaTion'有11个字母
s0: mov al, [bx]
or al, 00100000B;将a1中的ASCII码的第5位置为1,变为小写字母
mov [bx], al
inc bx
loop s0

mov ax, 4c00h
int 21h
codesg ends

2、[bx+idata]

[bx+idata]表示一个内存单元, 例如:mov ax, [bx+200]
该指令也可以写成如下格式:

1
2
3
4
5
mov ax, [200+bx]

mov ax, 200[bx]

mov ax, [bx].200

用[bx+idata]的方式进行数组的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
assume cs:codesg,ds:datasg 

datasg segment
db 'BaSiC';转为大写
db 'MinIx';转为小写
datasg ends

codesg segment
start:
mov ax, datasg
mov ds, ax
mov bx, 0 ;初始ds:bx

mov cx, 5
s: mov al, 0[bx]
and al, 11011111b ;转为大写字母
mov 0[bx], al ;写回
mov al, 5[bx] ;[5 + bx]
or al, 00100000b ;转为小写字母
mov 5[bx], al
inc bx
loop s

mov ax, 4c00h
int 21h
codesg ends
end start

C语言描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
char a[] = "BaSic";
char b[] = "MinIX";

int i = 0;

do
{
a[i] = a[i] & 0xDF;
b[i] = b[i] | 0x20;
i++;
} while(i < 5);

return 0;
}

3、SI 、DI 与 寻址方式的灵活应用

1、si 、di

si和di是8086CPU中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
assume cs: codesg, ds: datasg 

datasg segment
db 'welcome to masm!';用si和di实现将字符串‘welcome to masm!"复制到它后面的数据区中。
db '................'
datasg ends

codesg segment
start: mov ax, datasg
mov ds, ax
mov si, 0

mov cx, 8
s: mov ax, 0[si] ;[0 + si]
mov 16[si], ax ;[16 + si] 使用[bx +idata]方式代替di,使程序更简洁
add si, 2
loop s

mov ax, 4c00h
int 21h
codesg ends
end start

2、[bx + si] 和 [bx + di]

[bx+si]和[bx+di]的含义相似

[bx+si]表示一个内存单元,它的偏移地址为(bx)+(si)

指令mov ax, [bx + si]的含义:将一个内存单元字数据的内容送入ax,段地址在ds中

该指令也可以写成如下格式:mov ax, [bx][si]

3、[bx+si+idata]和[bx+di+idata]
[bx+si+idata]表示一个内存单元,它的偏移地址为(bx)+(si)+idata

指令mov ax,[bx+si+idata]的含义:将一个内存单元字数据的内容送入ax,段地址在ds中

4、不同的寻址方式的灵活应用
[idata]用一个常量来表示地址,可用于直接定位一个内存单元;
[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;
[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
[bx+si]用两个变量表示地址;
[bx+si+idata]用两个变量和一个常量表示地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
;将datasg段中每个单词改为大写字母
assume cs:codesg,ds:datasg,ss:stacksg

datasg segment
db 'ibm ' ;16
db 'dec '
db 'dos '
db 'vax ' ;看成二维数组
datasg ends

stacksg segment ;定义一个段,用来做栈段,容量为16个字节
dw 0, 0, 0, 0, 0, 0, 0, 0
stacksg ends

codesg segment
start: mov ax, stacksg
mov ss, ax
mov sp, 16
mov ax, datasg
mov ds, ax
mov bx, 0 ;初始ds:bx

;cx为默认循环计数器,二重循环只有一个计数器,所以外层循环先保存cx值,再恢复,我们采用栈保存
mov cx, 4
s0: push cx ;将外层循环的cx值入栈
mov si, 0
mov cx, 3 ;cx设置为内层循环的次数
s: mov al, [bx+si]
and al, 11011111b ;每个字符转为大写字母
mov [bx+si], al
inc si
loop s

add bx, 16 ;下一行
pop cx ;恢复cx值
loop s0 ;外层循环的loop指令将cx中的计数值减1

mov ax4c00H
int 21H
codesg ends
end start

七、数据处理的两个基本问题

1、 bx、si、di和bp

在8086CPU中,只有这4个寄存器可以用在“[…]”中来进行内存单元的寻址。

在[ ]中,这4个寄存器可以单个出现,或只能以4种组合出现:bx和si、bx和dibp和si、bp和di

只要在[……]中使用寄存器bp,而指令中没有显性地给出段地址, 段地址就默认在ss中

bx和bp当做基址寄存器,si和di当做变址寄存器。

bx,bp基址寄存器的区别:

bx可以寻址数据(ds)段,默认为ds段的基址,也可以寻址附加段(段跨越)。

bp只能寻址堆栈(ss)段,默认为ss段的基址,不允许段跨越。

注意是默认,也就是在不被特别指定时,作为这个段的基址。

CPU寻址过程

  1. 通过地址总线读取相应CS:IP地址指令
  2. 通过数据总线将读取的指令放入CPU中
  3. 将读取指令放入指令缓冲寄存器中
  4. 执行读取的指令将相应的指令操作完成,从bx偏移地址取值
  5. 将取出来的值通过数据总线放入ax

2、机器指令处理的数据在什么地方

数据处理大致可分为3类:读取、写入、运算。

在机器指令这一层来讲,并不关心数据的值是多少,而关心指令执行前一刻,它将要处理的数据所在的位置。指令在执行前,所要处理的数据可以在3个地方:CPU内部、内存、端口

3、汇编语言中数据位置的表达

汇编语言中用3个概念来表达数据的位置

  • 立即数(idata)
1
2
3
4
mov ax, 1                 ;对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器中)
add bx, 2000h ;在汇编语言中称为:立即数(idata)
or bx, 00010000b
mov al, 'a'
  • 寄存器
1
2
3
4
5
6
7
mov ax, bx     ;指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名。
mov ds, ax
push bx
mov ds:[0], bx
push ds
mov ss, ax
mov sp, ax
  • 段地址(SA)和偏移地址(EA)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
;指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出EA,SA在某个段寄存器中。
mov ax, [0]
mov ax, [di]
mov ax, [bx+8]
mov ax, [bx+si]
mov ax, [bx+si+8] ;以上段地址默认在ds中

mov ax, [bp]
mov ax, [bp+8]
mov ax, [bp+si]
mov ax, [bp+si+8] ;以上段地址默认在ss中

mov ax, ds:[bp]
mov ax, es:[bx]
mov ax, ss:[bx+si]
mov ax, cs:[bx+si+8] ;显式给出存放段地址的寄存器

4、指令要处理的数据有多长

8086CPU的指令,可以处理两种尺寸的数据,byte和word

  1. 通过寄存器名指明要处理的数据的尺寸。
    例如: mov al, ds:[0] 寄存器al指明了数据为1字节
  2. 在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为wordbyte
    例如:mov byte ptr ds:[0], 1 byte ptr 指明了指令访问的内存单元是一个字节单元
  3. 有些指令默认了访问的是字单元还是字节单元
    例如,push [1000H],push 指令只进行字操作。

5、寻址方式的综合应用

1
2
3
4
5
6
7
8
9
10
11
12
mov ax, seg 
mov ds, ax
mov bx, 60h ;确定记录地址,ds:bx

mov word ptr [bx+0ch], 38 ;排名字段改为38 [bx].0ch
add word ptr [bx+0eh], 70 ;收入字段增加70 [bx].0eh
mov si, 0 ;用si来定位产品字符串中的字符
mov byte ptr [bx+10h+si], 'V' ;[bx].10h[si]
inc si
mov byte ptr [bx+10h+si], 'A'
inc si
mov byte ptr [bx+10h+si], 'X'

C语言描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*定义一个公司记录的结构体*/
struct company
{
char cn[3];/*公司名称*/
char hn[9];/*总裁姓名*/
int pm;/*排名*/
int sr;/*收入*/
char cp[3];/*著名产品*/
};
//sizeof (struct company) == 24

int main()
{
/*定义一个公司记录的变量,内存中将存有一条公司的记录*/
struct company dec = {"DEC", "Ken Olsen", 137, 40, "PDP"};

int i;

dec.pm = 38;
dec.sr = dec.sr + 70;

i = 0;
dec.cp[i] = 'V'; //mov byte ptr [bx].10h[si], 'V'
i++;
dec.cp[i] = 'A';
i++;
dec.cp[i] = 'X';

return 0;
}

6、div指令、dd、dup、mul指令

div是除法指令

  1. 除数:有8位和16位两种,在一个寄存器内存单元中。
  2. 被除数:默认放在AXDX和AX中,
    如果除数为8位,被除数则为16位,默认在AX中存放;
    如果除数为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
  3. 结果:
    如果除数为8位,则AL存储除法操作的商AH存储除法操作的余数
    如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。
1
2
3
4
5
6
7
8
9
10
11
;利用除法指令计算100001/100。
;100001D = 186A1H
mov dx, 1
mov ax, 86A1H ;(dx)*10000H+(ax)=100001
mov bx, 100
div bx

;利用除法指令计算1001/100
mov ax, 1001
mov bl, 100
div b1

伪指令dd

db和dw定义字节型数据和字型数据。

dd是用来定义dword(double word,双字)型数据的伪指令

操作符dup

dup在汇编语言中同db、dw、dd等一样,也是由编译器识别处理的符号。
它和db、dw、dd等数据定义伪指令配合使用,用来进行数据的重复

1
2
3
db 3 dup (0)       ;定义了3个字节,它们的值都是0,相当于db 000
db 3 dup (0, 1, 2) ;定义了9个字节,它们是012012012,相当于db 012012012
db 3 dup ('abc', 'ABC') ;定义了18个字节,它们是abcABCabcABCabcABCC,相当于db 'abc', 'ABC' ,'abc' , 'ABC, 'abc', 'ABC'。

mul 指令

mul是乘法指令,使用 mul 做乘法的时候:相乘的两个数:要么都是8位,要么都是16位。

  • 8 位: AL中和 8位寄存器内存字节单元中;
  • 16 位: AX中和 16 位寄存器内存字单元中。

结果

  • 8位:AX中;
  • 16位:DX(高位)和 AX(低位)中。

格式:mul 寄存器mul 内存单元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
;计算10010
;10010小于255,可以做8位乘法
mov al,100
mov bl,10
mul bl

;结果: (ax)=100003E8H)

12345678
;计算10010000
;100小于255,可10000大于255,所以必须做16位乘法,程序如下:
mov ax,100
mov bx,10000
mul bx

;结果: (ax)=4240H,(dx)=000FH (F4240H=1000000

八、转移指令的原理


可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括地讲,转移指令就是可以控制CPU执行内存中某处代码的指令。

8086CPU的转移行为有以下几类。

  • 只修改IP时,称为段内转移,比如:jmp ax
  • 同时修改CS和IP时,称为段间转移,比如:jmp 1000:0

由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移

  • 短转移IP的修改范围为-128 ~ 127
  • 近转移IP的修改范围为-32768 ~ 32767

8086CPU的转移指令分为以下几类。

  • 无条件转移指令(如:jmp)
  • 条件转移指令
  • 循环指令(如:loop)
  • 过程
  • 中断

1、操作符offset

操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
;将s处的一条指令复制到s0处
assume cs:codesg
codesg segment
s: mov ax, bx ;(mov ax,bx 的机器码占两个字节)
mov si, offset s ;获得标号s的偏移地址
mov di, offset s0 ;获得标号s0的偏移地址

mov ax, cs:[si]
mov cs:[di], ax
s0: nop ;(nop的机器码占一个字节)
nop
codesg ends
ends

2、jmp指令

jmp为无条件转移,转到标号处执行指令可以只修改IP,也可以同时修改CS和IP;

jmp指令要给出两种信息:

  • 转移的目的地址
  • 转移的距离(段间转移、段内短转移,段内近转移)

    jmp short 标号 jmp near ptr 标号 jcxz 标号 loop 标号 等几种汇编指令,它们对 IP的修改

是根据转移目的地址和转移起始地址之间的位移来进行的。在它们对应的机器码中不包含转移的目的地址,而包含的是到目的地址的位移距离。

1)、依据位移进行转移的jmp指令

jmp short 标号(段内短转移)

指令“jmp short 标号”的功能为(IP)=(IP)+8位位移,转到标号处执行指令

(1)8位位移 = “标号”处的地址 - jmp指令后的第一个字节的地址;

(2)short指明此处的位移为8位位移;

(3)8位位移的范围为-128~127,用补码表示

(4)8位位移由编译程序在编译时算出。

1
2
3
4
5
6
7
8
assume cs:codesg
codesg segment
start:mov ax,0
jmp short s ;s不是被翻译成目的地址
add ax, 1
s:inc ax ;程序执行后, ax中的值为 1
codesg ends
end start

CPU不需要这个目的地址就可以实现对IP的修改。这里是依据位移进行转移

jmp short s指令的读取和执行过程:

  1. (CS)=0BBDH,(IP)=0006,上一条指令执行结束后CS:IP指向EB 03(jmp short s的机器码);
  2. 读取指令码EB 03进入指令缓冲器;
  3. (IP) = (IP) + 所读取指令的长度 = (IP) + 2 = 0008,CS:IP指向add ax,1;
  4. CPU指行指令缓冲器中的指令EB 03;
  5. 指令EB 03执行后,(IP)=000BH,CS:IP指向inc ax

jmp near ptr 标号 (段内近转移)

指令“jmp near ptr 标号”的功能为:(IP) = (IP) + 16位位移

2)、转移的目的地址在指令中的jmp指令

jmp far ptr 标号(段间转移或远转移)

指令 “jmp far ptr 标号” 功能如下:

  • (CS) = 标号所在段的段地址;
  • (IP) = 标号所在段中的偏移地址。
  • far ptr指明了指令用标号的段地址和偏移地址修改CS和IP。
1
2
3
4
5
6
7
8
9
10
assume cs:codesg
codesg segment
start: mov ax, 0
mov bx, 0
jmp far ptr s ;s被翻译成转移的目的地址0B01 BD0B
db 256 dup (0) ;转移的段地址:0BBDH,偏移地址:010BH
s: add ax,1
inc ax
codesg ends
end start

3)、转移地址在寄存器或内存中的jmp指令

1
jmp 16位寄存器` 功能:`IP =(16位寄存器)

转移地址在内存中的jmp指令有两种格式:

  • jmp word ptr 内存单元地址(段内转移)

功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。

1
2
3
4
mov ax, 0123H
mov ds:[0], ax
jmp word ptr ds:[0]
;执行后,(IP)=0123H
  • jmp dword ptr 内存单元地址(段间转移)

功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。

  1. (CS)=(内存单元地址+2)
  2. (IP)=(内存单元地址)
1
2
3
4
5
6
7
8
mov ax, 0123H
mov ds:[0], ax;偏移地址
mov word ptr ds:[2], 0;段地址
jmp dword ptr ds:[0]
;执行后,
;(CS)=0
;(IP)=0123H
;CS:IP 指向 0000:0123。

4)、jcxz指令和loop指令

jcxz指令

jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,

在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128~127。

指令格式:jcxz 标号(如果(cx)=0,则转移到标号处执行。)

当(cx) = 0时,(IP) = (IP) + 8位位移

  • 8位位移 = “标号”处的地址 - jcxz指令后的第一个字节的地址;
  • 8位位移的范围为-128~127,用补码表示;
  • 8位位移由编译程序在编译时算出。

当(cx)!=0时,什么也不做(程序向下执行)

loop指令

loop指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。

对IP的修改范围都为-128~127。

指令格式:loop 标号 ((cx) = (cx) - 1,如果(cx) ≠ 0,转移到标号处执行)。

(cx) = (cx) - 1;如果 (cx) != 0,(IP) = (IP) + 8位位移。

  • 8位位移 = 标号处的地址 - loop指令后的第一个字节的地址;
  • 8位位移的范围为-128~127,用补码表示;
  • 8位位移由编译程序在编译时算出。

如果(cx)= 0,什么也不做(程序向下执行)。

九、call和ret指令


call和ret指令都是转移指令,它们都修改IP,或同时修改CS和IP。

1、ret 和 retf

  • ret指令用栈中的数据,修改IP的内容,从而实现近转移;
  • retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移。

CPU执行ret指令时,相当于进行: pop IP

(1)(IP) = ( (ss) * 16 + (sp) )

(2)(sp) = (sp) + 2

CPU执行retf指令时,相当于进行:pop IP, pop CS

(1)(IP) = ( (ss) * 16 + (sp) )

(2)(sp) = (sp) + 2

(3)(CS) = ( (ss) * 16 + (sp) )

(4)(sp) = (sp) + 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
assume cs:code 
stack seqment
db 16 dup (0)
stack ends

code segment
mov ax, 4c00h
int 21h
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, 0
push ax ;ax入栈
mov bx, 0
ret ;ret指令执行后,(IP)=0,CS:IP指向代码段的第一条指令。可以push cs push ax retf
code ends
end start

2、call 指令

call指令经常跟ret指令配合使用,因此CPU执行call指令,进行两步操作:

(1)将当前的 IP 或 CS和IP 压入栈中;

(2)转移(jmp)。

call指令不能实现短转移,除此之外,call指令实现转移的方法和 jmp 指令的原理相同。

call 标号(近转移)

CPU执行此种格式的call指令时,相当于进行 push IP jmp near ptr 标号

call far ptr 标号(段间转移)

CPU执行此种格式的call指令时,相当于进行:push CS,push IP jmp far ptr 标号

1
call 16位寄存器

CPU执行此种格式的call指令时,相当于进行: push IP jmp 16位寄存器

1
call word ptr 内存单元地址

CPU执行此种格式的call指令时,相当于进行:push IP jmp word ptr 内存单元地址

1
2
3
4
5
6
7
mov sp, 10h
mov ax, 0123h
mov ds:[0], ax
call word ptr ds:[0]
;执行后,(IP)=0123H,(sp)=0EH
12345
call dword ptr 内存单元地址

CPU执行此种格式的call指令时,相当于进行:push CS push IP jmp dword ptr 内存单元地址

1
2
3
4
5
6
mov sp, 10h
mov ax, 0123h
mov ds:[0], ax
mov word ptr ds:[2], 0
call dword ptr ds:[0]
;执行后,(CS)=0,(IP)=0123H,(sp)=0CH

3、call 和 ret 的配合使用

分析下面程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
assume cs:code
code segment
start: mov ax,1
mov cx,3
call s ;(1)CPU指令缓冲器存放call指令,IP指向下一条指令(mov bx, ax),执行call指令,IP入栈,jmp

mov bx,ax ;(4)IP重新指向这里 bx = 8
mov ax,4c00h
int 21h
s: add ax,ax
loop s;(2)循环3次ax = 8
ret;(3)return : pop IP
code ends
end start

call 与 ret 指令共同支持了汇编语言编程中的模块化设计

编写子程序

十、标志寄存器


1、标志寄存器

CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作用。

(1)用来存储相关指令的某些执行结果;

(2)用来为CPU执行相关指令提供行为依据;

(3)用来控制CPU的相关工作方式。

这种特殊的寄存器在8086CPU中,被称为标志寄存器(flag)。

8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW-Program Status Word)

flag寄存器是按位起作用的,它的每一位都有专门的含义,记录特定的信息。

在8086CPU的指令集中,有的指令的执行是影响标志寄存器的,比如,add、sub、mul、div、inc、or、and等,它们大都是运算指令(进行逻辑或算术运算);有的指令的执行对标志寄存器没有影响,比如,mov、push、pop等,它们大都是传送指令

1)、零标志位 (ZF)

零标志位(Zero Flag)。它记录相关指令执行后,其结果是否为0。

如果结果为0,那么zf = 1(表示结果是0);如果结果不为0,那么zf = 0。

1
2
3
4
5
mov ax, 1
sub ax, 1 ;执行后,结果为0,则zf = 1

mov ax, 2
sub ax, 1 ;执行后,结果不为0,则zf = 0

2)、奇偶标志位 (PF)

奇偶标志位(Parity Flag)。它记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数。

如果1的个数为偶数,pf = 1,如果为奇数,那么pf = 0。

1
2
3
4
5
mov al, 1
add al, 10 ;执行后,结果为00001011B,其中有3(奇数)个1,则pf = 0

mov al, 1
or al, 2 ;执行后,结果为00000011B,其中有2(偶数)个1,则pf = 1

3)、符号标志位(SF)

符号标志位(Symbol Flag)。它记录相关指令执行后,其结果是否为负。

如果结果为负,sf = 1;如果非负,sf = 0。

计算机中通常用补码来表示有符号数据。计算机中的一个数据可以看作是有符号数,也可以看成是无符号数。

00000001B,可以看作为无符号数1,或有符号数+1;
10000001B,可以看作为无符号数129,也可以看作有符号数-127。

对于同一个二进制数据,计算机可以将它当作无符号数据来运算,也可以当作有符号数据来运算

CPU在执行add等指令的时候,就包含了两种含义:可以将add指令进行的运算当作无符号数的运算,也可以将add指令进行的运算当作有符号数的运算

SF标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负。在我们将数据当作有符号数来运算的时候,可以通过它来得知结果的正负。如果我们将数据当作无符号数来运算,SF的值则没有意义,虽然相关的指令影响了它的值

1
2
3
4
5
mov al, 10000001B 
add al, 1 ;执行后,结果为10000010B,sf = 1,表示:如果指令进行的是有符号数运算,那么结果为负;
12
mov al, 10000001B
add al, 01111111B ;执行后,结果为0,sf = 0,表示:如果指令进行的是有符号数运算,那么结果为非负

4)、进位标志位(CF)

进位标志位(Carry Flag)。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值

97H - 98H 产生借位CF = 1 ==》 (al) = 197H - 98H = FFH

5)、溢出标志位(OF)

溢出标志位(Overflow Flag)。一般情况下,OF记录了有符号数运算的结果是否发生了溢出。

如果发生溢出,OF = 1;如果没有,OF = 0。

CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位

CPU在执行add等指令的时候,就包含了两种含义:无符号数运算和有符号数运算。

  • 对于无符号数运算,CPU用CF位来记录是否产生了进位;
  • 对于有符号数运算,CPU用OF位来记录是否产生了溢出,当然,还要用SF位来记录结果的符号。
1
2
3
4
5
6
7
8
9
10
11
mov al, 98
add al, 99 ;执行后将产生溢出。因为进行的"有符号数"运算是:(al)=(al)+ 99 = 98 + 99=197 = C5H 为-59的补码
;而结果197超出了机器所能表示的8位有符号数的范围:-128-127
;add 指令执行后:无符号运算没有进位CF=0,有符号运算溢出OF=1
;当取出的数据C5H按无符号解析C5H = 197, 当按有符号解析通过SP得知数据为负,即C5H为-59补码存储,

mov al,0F0H ;F0H,为有符号数-16的补码 -Not(F0 - 1)
add al,088H ;88H,为有符号数-120的补码 -Not(88- 1)
;执行后,将产生溢出。因为add al, 088H进行的有符号数运算结果是:(al)= -136
;而结果-136超出了机器所能表示的8位有符号数的范围:-128-127
;add 指令执行后:无符号运算有进位CF=1,有符号运算溢出OF=1

2、adc指令和sbb指令

adc是带进位加法指令,它利用了CF位上记录的进位值。

指令格式:adc 操作对象1, 操作对象2

功能:操作对象1 = 操作对象1 + 操作对象2 + CF

1
2
3
4
5
6
7
8
9
10
11
mov ax, 2
mov bx, 1
sub bx, ax ;无符号运算借位CF=1,有符号运算OF = 0
adc ax, 1 ;执行后,(ax)= 4。adc执行时,相当于计算:(ax)+1+CF = 2+1+1 = 4

;计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。
;将计算分两步进行,先将低16位相加,然后将高16位和进位值相加。
mov ax, 001EH
mov bx, 0F000H
add bx, 1000H
adc ax, 0020H

sbb指令

sbb是带借位减法指令,它利用了CF位上记录的借位值。

指令格式:sbb 操作对象1, 操作对象2

功能:操作对象1 = 操作对象1 - 操作对象2 - CF

1
2
3
4
5
;计算 003E1000H - 00202000H,结果放在ax,bx中,程序如下:
mov bx, 1000H
mov ax, 003EH
sub bx, 2000H
sbb ax, 0020H

3、cmp指令

cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响。

其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

cmp指令格式:cmp 操作对象1,操作对象2

例如:
指令cmp ax, ax,做(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关各位。
指令执行后:zf=1,pf=1,sf=0,cf=0,of=0。

CPU在执行cmp指令的时候,也包含两种含义:进行无符号数运算和进行有符号数运算。

cmp ax, bx 无符号比较时
(ax) = (bx) zf = 1
(ax) ≠ (bx) zf = 0
(ax) < (bx) cf = 1
(ax) ≥ (bx) cf = 0
(ax) > (bx) cf = 0 且 zf = 0
(ax) ≤ (bx) cf = 1 且 zf = 1

上面的表格可以正推也可以逆推

如果用cmp来进行有符号数比较时
SF只能记录实际结果的正负,发生溢出的时候,实际结果的正负不能说明逻辑上真正结果的正负。
但是逻辑上的结果的正负,才是cmp指令所求的真正结果,所以我们在考察SF的同时考察OF,就可以得知逻辑上真正结果的正负,同时就知道比较的结果。

1
2
3
4
5
mov ah, 08AH  ; -Not(8A-1) = -118  即当成有符号数时为-118
mov bh, 070H ; 有符号数时最高位为0为正数, 70H = 112
cmp ah, bh ;(ah)-(bh)实际得到的结果是1AH
; 在逻辑上,运算所应该得到的结果是:(-118)- 112 = -230
; sf记录实际结果的正负,所以sf=0

cmp ah, bh
(1)如果sf=1,而of=0 。 of=0说明没有溢出,逻辑上真正结果的正负=实际结果的正负; sf=1,实际结果为负,所以逻辑上真正的结果为负,所以(ah)<(bh)

(2)如果sf=1,而of=1: of=1,说明有溢出,逻辑上真正结果的正负≠实际结果的正负; sf=1,实际结果为负。
实际结果为负,而又有溢出,这说明是由于溢出导致了实际结果为负,,如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。 这样,sf=1,of=1,说明了(ah)>(bh)。

(3)如果sf=0,而of=1。of=1,说明有溢出,逻辑上真正结果的正负≠实际结果的正负;sf=0,实际结果非负。而of=1说明有溢出,则结果非0,所以,实际结果为正。
实际结果为正,而又有溢出,这说明是由于溢出导致了实际结果非负,如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负。这样,sf=0,of=1,说明了(ah)<(bh)。
(4)如果sf=0,而of=0
of=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负;sf=0,实际结果非负,所以逻辑上真正的结果非负,所以(ah)≥(bh)。

4、检测比较结果的条件转移指令

可以根据某种条件,决定是否修改IP的指令

jcxz它可以检测cx中的数值,如果(cx)=0,就修改IP,否则什么也不做。

所有条件转移指令的转移位移都是[-128,127]。

多数条件转移指令都检测标志寄存器的相关标志位,根据检测的结果来决定是否修改IP

这些条件转移指令通常都和cmp相配合使用,它们所检测的标志位,都是cmp指令进行无符号数比较的时记录比较结果的标志位

根据无符号数的比较结果进行转移的条件转移指令(它们检测zf、cf的值)

指令 含义 检测的相关标志位
je 等于则转移 zf = 1
jne 不等于则转移 zf = 0
jb 低于则转移 cf = 1
jnb 不低于则转移 cf = 0
ja 高于则转移 cf = 0 且 zf = 0
jna 不高于则转移 cf = 1 且 zf = 1

j:jump,e:equal,b:below,a:above,n:not

1
2
3
4
5
6
7
8
9
10
11
12
13
;编程,统计data段中数值为8的字节的个数,用ax保存统计结果。
mov ax, data
mov ds, ax
mov bx, 0 ;ds:bx指向第一个字节
mov ax, 0 ;初始化累加器mov cx,8

s:
cmp byte ptr [bx], 8 ;和8进行比较
jne next ;如果不相等转到next,继续循环
inc ax ;如果相等就将计数值加1
next:
inc bx
loop s ;程序执行后:(ax)=3

5、DF标志和串传送指令

方向标志位。在串处理指令中,控制每次操作后si、di的增减。

  • df = 0每次操作后si、di递增;
  • df = 1每次操作后si、di递减。

格式:movsb
功能:将ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将si和di递增或递减

格式:movsw
功能:将ds:si指向的内存字单元中的字送入es:di中,然后根据标志寄存器df位的值,将si和di递增2或递减2。

格式:rep movsb
movsb和movsw进行的是串传送操作中的一个步骤,一般来说,movsb和movsw都和rep配合使用,
功能:rep的作用是根据cx的值,重复执行后面的串传送指令

8086CPU提供下面两条指令对df位进行设置。

  • cld指令:将标志寄存器的df位置0
  • std指令:将标志寄存器的df位置1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;将data段中的第一个字符串复制到它后面的空间中。
data segment
db 'Welcome to masm!'
db 16 dup (0)
data ends

mov ax, data
mov ds, ax
mov si, 0 ;ds:si 指向data:0
mov es, ax
mov di, 16 ;es:di指向data:0010

mov cx, 16 ;(cx)=16,rep循环16次
cld ;设置df=0,正向传送
rep movsb

6、pushf和popf

pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据,送入标志寄存器中

pushf和popf,为直接访问标志寄存器提供了一种方法。

十一、内中断

1、内中断的产生

任何一个通用的CPU,都具备一种能力,可以在执行完当前正在执行的指令之后,检测到从CPU外部发送过来的或内部产生的一种特殊信息,并且可以立即对所接收到的信息进行处理。这种特殊的信息,我们可以称其为:中断信息。中断的意思是指,CPU不再接着(刚执行完的指令)向下执行,而是转去处理这个特殊信息。

中断信息可以来自CPU的内部和外部(内中断,外中断)

内中断:当CPU的内部有需要处理的事情发生的时候,将产生中断信息,引发中断过程。这种中断信息来自CPU的内部

8086CPU的内中断(下面四种情况将产生中断信息)

  • 除法错误,比如,执行div指令产生的除法溢出;
  • 单步执行;
  • 执行 into指令;
  • 执行 int指令。

中断信息中包含中断类型码,中断类型码为一个字节型数据,可以表示256种中断信息的来源(中断源)

上述的4种中断源,在8086CPU中的中断类型码如下。

  • 除法错误:0
  • 单步执行:1
  • 执行into指令:4
  • 执行int指令,该指令的格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码。

2、中断处理程序、中断向量表、中断过程

中断处理程序

用来处理中断信息的程序被称为中断处理程序。

根据CPU的设计,中断类型码的作用就是用来定位中断处理程序。比如CPU根据中断类型码4,就可以找到4号中断的处理程序

中断向量表

中断向量就是中断处理程序的入口地址。中断向量表就是中断处理程序入口地址的列表

CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址

中断过程

中断过程的主要任务就是用中断类型码在中断向量表中找到中断处理程序的入口地址,设置CS和IP

简要描述如下

  1. 取得中断类型码N;
  2. pushf
  3. TF=0,IF=0 (为什么这样参考单步中断)
  4. push CS , push IP
  5. (IP)=(N * 4),(CS)=(N * 4 + 2)

硬件在完成中断过程后,CS:IP将指向中断处理程序的入口,CPU开始执行中断处理程序。

3、iret指令

CPU随时都可能执行中断处理程序,中断处理程序必须一直存储在内存某段空间之中
而中断处理程序的入口地址,即中断向量,必须存储在对应的中断向量表表项中。

中断处理程序的常规编写步骤:

  1. 保存用到的寄存器;
  2. 处理中断;
  3. 恢复用到的寄存器;
  4. iret指令返回。

iret 指令描述为:pop IP pop CS popf

iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序

4、除法错误中断的处理

1
2
3
mov ax, 1000h 
mov bh, 1
div bh ;除法溢出错误

1、当CPU执行div bh时,发生了除法溢出错误,产生0号中断信息,从而引发中断过程,

2、CPU执行0号中断处理程序

3、系统中的0号中断处理程序的功能:显示提示信息“Divide overflow”后,返回到操作系统中。

编程实验

编程:编写0号中断处理程序do0,当发生除法溢出时,在屏幕中间显示“overflow!”,返回DOS。

1、0000:0200至0000:02FF的256个字节的空间所对应的中断向量表项都是空的,可以将中断处理程序do0传送到内存0000:0200处。

2、中断处理程序do0放到0000:0200,再将其地址登记在中断向量表对应表项

  • 0号表项的地址0:00:0字单元存放偏移地址,0:2字单元存放段地址
  • 将do0的段地址0存放在0000:0002字单元中,将偏移地址200H存放在0000:0000字单元
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
assume cs:code

code segment
start:
mov ax, cs
mov ds, ax
mov si, offset do0 ;设置ds:si指向源地址
mov ax, 0
mov es, ax
mov di, 200h ;设置es:di指向目的地址0000:0200
mov cx, offset do0end - offset do0 ;设置cx为传输长度 编译时给出do0部分代码长度
cld ;设置传输方向为正
rep movsb ;将do0的代码送入0:200处

mov ax, 0 ;设置中断向量表
mov es, ax
mov word ptr es:[04], 200h
mov word ptr es:[04+2], 0

mov ax,4c00h
int 21h

;do0程序的主要任务是显示字符串
do0: jmp short do0 start
db "overflow!"

do0start:
mov ax, cs
mov ds, ax
mov si, 202h ;设置ds:si指向字符串

mov ax, 0b800h
mov es, ax
mov di, 12160+362 ;设置es:di指向显存空间的中间位置

mov cx, 9 ;设置cx为字符串长度
s: mov al, [si]
mov es:[di], al
inc si
add di, 1
mov al, 02h ;设置颜色
mov es:[di], al
add di, 1
loop s

mov ax, 4c00h
int 21h
do0end: nop

code ends
end start

5、单步中断

    • TF陷阱标志(trap flag):用于调试的单步方式操作
    • TF = 1时每条指令执行后产生陷阱,由系统控制计算机
    • TF = 0时CPU正常工作
    • IF中断标志(interrupt flag)
    • IF = 1允许CPU响应可屏蔽中断请求
    • IF = 0关闭中断

CPU在执行完一条指令之后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1

Debug是如何利用CPU所提供的单步中断的功能进行调试?如使用t命令查看寄存器状态

Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令

在使用t命令执行指令时,Debug将TF设置为1,在CPU执行完这条指令后就引发单步中断,执行单步中断的中断处理程序,所有寄存器中的内容被显示在屏幕上,并且等待输入命令。

在进入中断处理程序之前,设置TF=0。从而避免CPU在执行中断处理程序的时候发生单步中断

6、int指令

int指令的格式为:int n ,n为中断类型码,它的功能是引发中断过程。

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

在程序中使用int指令调用任何一个中断的中断处理程序(中断例程)

编写供应用程序调用的中断例程

实验1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
;求2 * 3456^2
assume cs:code

code segment

start:
mov ax, 3456 ;(ax)=3456
int 7ch ; 调用中断7ch的中断例程,计算ax中的数据的平方
add ax, ax
adc dx, dx ;存放结果,将结果乘以2

mov ax,4c00h
int 21h
code ends
end start

;编程:安装中断7ch的中断例程
;功能:求一word型数据的平方。
;参数:(ax) = 要计算的数据。
;返回值:dx、ax中存放结果的高16位和低16位。

assume cs:code

code segment
start:
mov ax,cs
mov ds,ax
mov si,offset sqr ;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置es:di指向目的地址
mov cx,offset sqrend - offset sqr ;设置cx为传输长度
cld ;设置传输方向为正
rep movsb

mov ax,0
mov es,ax
mov word ptr es:[7ch4], 200h
mov word ptr es:[7ch4+2], 0

mov ax,4c00h
int 21h

sqr:
mul ax
iret ;CPU执行int 7ch指令进入中断例程之前,标志寄存器、当前的CS和IP被压入栈
;在执行完中断例程后,应该用iret 指令恢复int 7ch执行前的标志寄存器和CS、IP的
sqrend: nop

code ends
end start

实验2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
;功能:将一个全是字母,以0结尾的字符串,转化为大写。
;参数:ds:si指向字符串的首地址。
;应用举例:将data段中的字符串转化为大写。
assume cs:code

data segment
db 'conversation',0
data ends

code segment
start: mov ax, data
mov ds, ax
mov si, 0
int 7ch

mov ax,4c00h
int 21h
code ends
end start

assume cs:code
code segment

start:
mov ax,cs
mov ds,ax
mov si,offset capital
mov ax,0
mov es,ax
mov di,200h
mov cx,offset capitalend - offset capital
cld
rep movsb

mov ax,0
mov es,ax
mov word ptr es:[7ch4],200h
mov word ptr es:[7ch4+2],0

mov ax,4c00h
int 21h

capital:
push cx
push si

change:
mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short change
ok:
pop si
pop cx
iret

capitalend:nop

code ends

end start

7、BIOS和DOS所提供的中断例程

在系统板的ROM中存放着一套程序,称为BIOS(基本输入输出系统)

BIOS中主要包含以下几部分内容

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

程序员在编程的时候,可以用int 指令直接调用BIOS和DOS系统提供的中断例程,来完成某些工作。
和硬件设备相关的DOS中断例程中,一般都调用了BIOS的中断例程。

BIOS和DOS中断例程的安装过程

BIOS和DOS提供的中断例程是如何安装到内存中的呢?

1、开机后,CPU一加电,初始化(CS)= 0FFFFH,(IP)= 0,自动从FFFF:0单元开始执行程序。FFFF:0处有一条转跳指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。

2、初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。
注意,对于BIOS所提供的中断例程,只需将入口地址登记在中断向量表中即可,因为它们是固化到ROM中的程序,一直在内存中存在。

3、硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。从此将计算机交由操作系统控制。

4、DOS启动后,除完成其他工作外,还将它所提供的中断例程装入内存,并建立相应的中断向量。

BIOS中断例程应用

一般来说,一个供程序员调用的中断例程中往往包括多个子程序,中断例程内部用传递进来的参数来决定执行哪一个子程序。

BIOS和DOS提供的中断例程,都用 ah 来传递内部子程序的编号。

编程:在屏幕的5行12列显示3个红底高亮闪烁绿色的“al。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assume cs:code 

code segment
;int 10h中断例程的"设置光标位置"功能
mov ah, 2;设置光标调用第10h号中断例程的2号子程序,功能为设置光标位置(可以提供光标所在的行号、列号和页号作为参数)

;设置光标到第0页,第5行,第12列
mov bh, 0;第0
mov dh, 5dh中放行号
mov dl, 12dl中放列号
int 10h

;int10h中断例程的"在光标位置显示字符"功能。
mov ah9 ;调用第10h号中断例程的9号子程序,功能为在光标位置显示字符
;提供要显示的字符、颜色属性、页号、字符重复个数作为参数
mov al'a' ;字符
mov b1,11001010b ;颜色属性
mov bh0 ;第0页
mov cx3 ;字符重复个数
int 10h

code ends
end

bh中页号的含义:内存地址空间中,B8000H~BFFFFH共32kB的空间,为80*25彩色字符模式的显示缓冲区。
一屏的内容在显示缓冲区中共占4000个字节。显示缓冲区分为8页,每页4KB(约4000B),显示器可以显示任意一页的内容。一般情况下,显示第0页的内容。也就是说,通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上。

DOS中断例程应用
int 21h中断例程是DOS提供的中断例程,4ch号功能,即程序返回功能

1
2
3
mov ah, 4ch ;调用第21h号中断例程的4ch号子程序,功能为程序返回,可以提供返回值作为参数
mov al, 0 ;返回值
int 21h

编程:在屏幕的5行12列显示字符串“Welcome to masm!”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assume cs:code 

data segment
db 'Welcome to masm', '$' ;“$”本身并不显示,只起到边界的作用
data ends

code segment
start: mov ah, 2 ;10号中断设置光标位置功能
mov bh, 0 ;第0页
mov dh, 5dh中放行号
mov dl, 12 ;dl中放列号
int 10h

mov ax, data
mov ds, ax
mov dx, 0 ;ds:dx指向字符串的首地址data:0 (参数)
mov ah, 9 ;调用第21h号中断例程的9号子程序,功能为在光标位置显示字符串,可以提供要显示字符串的地址作为参数
int 21h

mov ax, 4c00h ;21号中断程序返回功能
int 21h
code ends
end start

十二、端口

在PC机系统中,和CPU通过总线相连的芯片除各种存储器外,还有以下3种芯片。

  • 各种接口卡(比如,网卡、显卡)上的接口芯片,它们控制接口卡进行工作;
  • 主板上的接口芯片,CPU通过它们对部分外设进行访问;
  • 其他芯片,用来存储相关的系统信息,或进行相关的输入输出处理。

在这些芯片中,都有一组可以由CPU读写的寄存器。这些寄存器,它们在物理上可能处于不同的芯片中,
但是它们在以下两点上相同。

  • 都和CPU的总线相连,这种连接是通过它们所在的芯片进行的;
  • CPU对它们进行读或写的时候都通过控制线向它们所在的芯片发出端口读写命令。

从CPU的角度,将这些寄存器都当作端口,对它们进行统一编址,从而建立了一个统一的端口地址空间。
每一个端口在地址空间中都有一个地址。在访问端口的时候,CPU通过端口地址来定位端口。因为端口所在的芯片和CPU通过总线相连,

CPU可以直接读写以下3个地方的数据。

  • CPU内部的寄存器;
  • 内存单元;
  • 端口。

1、端口的读写

端口地址和内存地址一样,通过地址总线来传送。在PC系统中,CPU最多可以定位64KB个不同的端口。则端口地址的范围为0-65535

端口的读写指令只有两条:inout,分别用于从端口读取数据和往端口写入数据。

在in和out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据。

1
2
3
4
5
6
7
8
;对0~255以内的端口进行读写时:
in al, 20h ;从20h端口读入一个字节
out 20h, al ;往20h端口写入一个字节

;对256~65535的端口进行读写时,端口号放在dx中:
mov dx, 3f8h ;将端口号3f8h送入dx
in al, dx ;从3f8h端口读入一个字节
out dx, al ;向3f8h端口写入一个字节

2、CMOS RAM芯片

PC机中,有一个CMOS RAM芯片,一般简称为CMOS。此芯片的特征如下

  • 包含一个实时钟和一个有128个存储单元的RAM存储器
  • 该芯片靠电池供电。关机后内部的实时钟正常工作,RAM中的信息不丢失
  • 128个字节的RAM中,内部实时钟占用0~0dh单元来保存时间信息,其余大部分单元用于保存系统配置信息,供系统启动时BIOS程序读取。BIOS也提供了相关的程序,使我们可以在开机的时候配置CMOS RAM中的系统信息。
  • 该芯片内部有两个端口,端口地址为70h和71h。CPU通过这两个端口来读写CMOS RAM
  • 70h为地址端口,存放要访问的CMOS RAM单元的地址;71h为数据端口,存放从选定的CMOS RAM单元中读取的数据,或要写入到其中的数据。
    可见,CPU对CMOS RAM的读写分两步进行,比如,读CMOS RAM的2号单元:
    ①将2送入端口70h;
    ②从端口71h读出2号单元的内容。

CMOS RAM中存储的时间信息

在CMOS RAM中,存放着当前的时间:年、月、日、时、分、秒。长度都为1个字节,
存放单元为:

9 8 7 6 5 4 3 2 1 0

BCD码是以4位二进制数表示十进制数码的编码方法 4 == 0100B

一个字节可表示两个BCD码。则CMOS RAM存储时间信息的单元中,存储了用两个BCD码表示的两位十进制数,高4位的BCD码表示十位,低4位的BCD码表示个位。比如,00010100b表示14。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
;编程,在屏幕中间显示当前的月份。
assume cs:code
code segment
start: mov al8 ;从CMOS RAM的8号单元读出当前月份的BCD码。
out 70hal
in al, 71h ;从数据端口71h中取得指定单元中的数据:

mov ah, al ;al中为从CMOS RAM的8号单元中读出的数据
mov cl, 4
shr ah, cl ;ah中为月份的十位数码值,左移四位空出四位
and al, 00001111b ;al中为月份的个位数码值

add ah, 30h ;BCD码值+30h=十进制数对应的ASCII
add al, 30h

mov bx, 0b800h
mov es, bx
mov byte ptr es:[16012+402], ah ;显示月份的十位数码
mov byte ptr es:[16012+402+2], al ;接着显示月份的个位数码

mov ax4c00h
int 21h
code ends
end start

3、shl和shr指令

shl和shr是逻辑移位指令

shl是逻辑左移指令,它的功能为:

  1. 将一个寄存器或内存单元中的数据向左移位;
  2. 将最后移出的一位写入CF中;
  3. 最低位用0补充。

shr是逻辑右移指令,同理

1
2
3
4
5
6
7
8
9
mov al, 01001000b 
shl al, 1 ;将a1中的数据左移一位执行后(al)=10010000b,CF=0。

mov al, 01010001b
mov cl, 3 ;如果移动位数大于1时,必须将移动位数放在cl中
shl al, c1

mov al, 10000001b
shr al, 1 ;将al中的数据右移一位执行后(al)=01000000b,CF=1。

将X逻辑左移一位,相当于执行X=X*2。
将X逻辑右移一位,相当于执行X=X/2

十三、外中断

1、外中断

CPU在计算机系统中,除了能够执行指令,进行运算以外,还应该能够对外部设备进行控制,接收它们的输入,向它们进行输出(I/O能力)

PC系统的接口卡和主板上,装有各种接口芯片。这些外设接口芯片的内部有若干寄存器,CPU将这些寄存器当作端口来访问

外设的输入不直接送入内存和CPU,而是送入相关的接口芯片的端口中;
CPU向外设的输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设。
CPU还可以向外设输出控制命令,而这些控制命令也是先送到相关芯片的端口中,然后再由相关的芯片根据命令对外设实施控制。

即:CPU通过端口和外部设备进行联系

当CPU外部有需要处理的事情发生的时候,比如说,外设的输入到达,相关芯片将向CPU发出相应的中断信息。CPU在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设的输入。

PC系统中,外中断源有两类

1、可屏蔽中断

可屏蔽中断是CPU可以不响应的外中断。CPU是否响应可屏蔽中断,要看标志寄存器的IF位的设置。
当CPU检测到可屏蔽中断信息时,如果IF=1,则CPU在执行完当前指令后响应中断,引发中断过程;如果IF=0,则不响应可屏蔽中断。

可屏蔽中断信息来自于CPU外部,中断类型码是通过数据总线送入CPU的;而内中断的中断类型码是在CPU内部产生的。

中断过程中将IF置0的原因就是,在进入中断处理程序后,禁止其他的可屏蔽中断。
如果在中断处理程序中需要处理可屏蔽中断,可以用指令将IF置1。

8086CPU提供的设置IF的指令:sti,设置IF=1;cli,设置IF=0。

2、不可屏蔽中断

不可屏蔽中断是CPU必须响应的外中断。当CPU检测到不可屏蔽中断信息时,则在执行完当前指令后,立即响应,引发中断过程。

对于8086CPU,不可屏蔽中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码。则不可屏蔽中断的中断过程为:①标志寄存器入栈,IF=0,TF=0;②CS、IP入栈;③(IP)=(8),(CS)=(0AH)。

几乎所有由外设引发的外中断,都是可屏蔽中断。当外设有需要处理的事件(比如说键盘输入)发生时,相关芯片向CPU发出可屏蔽中断信息。不可屏蔽中断是在系统中有必须处理的紧急情况发生时用来通知CPU的中断信息。

2、PC机键盘的处理过程

键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。按下一个键时,开关接通,该芯片就产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60h。松开按下的键时,也产生一个扫描码,扫描码说明了松开的键在键盘上的位置。松开按键时产生的扫描码也被送入60h端口中。

一般将按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。

扫描码长度为一个字节,通码的第7位为0,断码的第7位为1
即:断码 = 通码 + 80h。比如,g键的通码为22h,断码为a2h

键盘的输入到达60h端口时,相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息。CPU检测到该中断信息后,如果IF=1,则响应中断,引发中断过程,转去执行int 9中断例程。

BIOS提供了int 9中断例程,用来进行基本的键盘输入处理,主要的工作如下:
(1)读出60h端口中的扫描码;
(2)如果是字符键的扫描码,将该扫描码和它所对应的字符码(即ASCII码)送入内存中的BIOS键盘缓冲区; 如果是控制键(比如Ctrl)和切换键(比如CapsLock)的扫描码,则将其转变为状态字节写入内存中存储状态字节的单元;
(3)对键盘系统进行相关的控制,比如说,向相关芯片发出应答信息。

BIOS键盘缓冲区可以存储15个键盘输入,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。

0040:17单元存储键盘状态字节,该字节记录了控制键和切换键的状态。键盘状态字节各位记录的信息如下。

0 右shift状态 置1表示按下右shift键
1 左shift状态 置1表示按下左shift键
2 Ctrl状态 置1表示按下Ctrl键
3 Alt状态 置1表示按下Alt键
4 ScrollLock状态 置1表示Scroll指示灯亮
5 NumLock状态 置1表示小键盘输入的是数字
6 CapsLock状态 置1表示输入大写字母
7 Insert状态 置1表示处于删除态

编写int 9中断例程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
;编程:在屏幕中间依次显示“a”~“z”,并可以让人看清。在显示的过程中,按下'Esc'键后,改变显示的颜色。

;完整功能代码:

assume cs:code

stack segment
db 128 dup (0)
stack ends

data segment
dw 0,0
data ends

code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
mov ax,0
mov es,ax

push es:[94]
pop ds:[0]
push es:[94+2]
pop ds:[2] ;将原来的int 9中断例程的入口地址保存在ds:0、ds:2单元中

mov word ptr es:[94], offset int9
mov es:[94+2], cs ;在中断向量表中设置新的int 9中断例程的入口地址

;显示字符串
mov ax, 0b800h
mov es, ax
mov ah, 'a'
s:
mov es:[16012+402], ah
call delay
inc ah
cmp ah, 'z'
jna s
mov ax,0
mov es,ax

push ds:[0]
pop es:[94]
push ds;[2]
pop es;[9*4+2] ;将中断向量表中int 9中断例程的入口恢复为原来的地址

mov ax,4c00h
int 21h

;将循环延时的程序段写为一个子程序
delay:
push ax
push dx
mov dx, 2000h ;用两个16位寄存器来存放32位的循环次数
mov ax, 0
s1:
sub ax, 1
sbb dx, 0
cmp ax, 0
jne s1
cmp dx, 0
jne s1
pop dx
pop ax
ret

;------以下为新的int 9中断例程--------------------

int9:
push ax
push bx
push es

in al, 60h;从端口60h读出键盘的输入

pushf ;标志寄存器入栈

pushf
pop bx
and bh,11111100b
push bx
popf ;TF=0,IF=0

call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int 9中断例程

cmp al,1
jne int9ret

mov ax,0b800h
mov es,ax
inc byte ptr es:[16012+402+1] ;属性增加1,改变颜色

int9ret:
pop es
pop bx
pop ax
iret

code ends

end start

CPU对外设输入的通常处理方法
(1)外设的输入送入端口;
(2)向CPU发出外中断(可屏蔽中断)信息;
(3)CPU检测到可屏蔽中断信息,如果IF=1,CPU在执行完当前指令后响应中断,执行相应的中断例程;
(4)可在中断例程中实现对外设输入的处理。

端口和中断机制,是CPU进行I/O的基础。

十四、直接定址表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code
code segment
a : db 1,2,3,4,5,6,7,8 ;在后面加有“:”的地址标号,只能在代码段中使用,不能在其他段中使用。
b : dw 0
start :mov si,offset a
mov bx,offset b
mov cx,8
s : mov al,cs:[si]
mov ah,0
add cs:[bx],ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start

程序中,code、a、b、start、s都是标号。这些标号仅仅表示了内存单元的地址

描述了单位长度的标号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code
code segment
a db 1,2,3,4,5,6,7,8 ;标号a、b后面没有":",因此它们是可以同时描述内存地址和单元长度的标号。
;标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元
b dw 0 ;标号b描述了地址code:8,和从这个地址开始,以后的内存单元都是字单元。
start : mov si,0
mov cx,8
s : mov al,a[si]
mov ah,0
add b,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start

使用数据标号来描述存储数据的单元的地址和长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
assume cs:code,ds:data ;用伪指令assume将标号所在的段和一个段寄存器联系起来(编译器需要)
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start: mov ax,data
mov ds,ax ;真正确定ds寄存器
mov si,0
mov cx,8
s: mov al,a[si] ;编译为:mov al,[si+0] 默认所访问单元的段地址在ds
mov ah,0
add b,ax ;编译为:add [8],ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start

data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw a, b ;等价于c dw offset a, offset b
;数据标号c处存储的两个字型数据为标号a、b 的偏移地址
data ends

data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dd a,b ;等价于c dw offset a, seg a, offset b, seg b
;数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b 的偏移地址和段地址
data ends

seg操作符,功能为取得某一标号的段地址

建立一张表,表中依次存储字符“0”~“F”,我们可以通过数值0 ~ 15直接查找到对应的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
assume cs:code

code segment
start:
mov al,0eh

call showbyte

mov ax,4c00h
int 21h

;子程序:
;用al传送要显示的数据

showbyte:
jmp short show

table db '0123456789ABCDEF' ;字符表

show: push bx
push es

mov ah,al
shr ah,1
shr ah,1
shr ah,1
shr ah,1 ;右移4位,ah中得到高4位的值
and al,00001111b ;al中为低4位的值

mov bl,ah
mov bh,0
mov ah,table[bx] ;用高4位的值作为相对于table的偏移,取得对应的字符

mov bx,0b800h
mov es,bx
mov es:[16012+402],ah

mov bl,al
mov bh,0
mov al,table[bx] ;用低4位的值作为相对于table的偏移,取得对应的字符

mov es:[16012+402+2],al

pop es
pop bx
ret

code ends
end start

十五、 总结

1、寄存器分类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
通用寄存器:       EAXEBXECXEDX:是ax,bx,cx,dx的延伸,各为32
AHAL=AX(accumulator) :累加寄存器
BHBL=BX(base) :基址寄存器
CHCL=CX(count) :计数寄存器
DHDL=DX(data) :数据寄存器
特殊功能寄存器: ESPEBPESIEDIEIP:是sp,bp,si,di,ip的延伸,32
SP(Stack Pointer) :堆栈指针寄存器(存放栈顶的偏移地址)
BP(Base Pointer) :基址指针寄存器(堆栈区中的一个基址地址)
SI(Source Index) :源变址寄存器
DI(Destination Index) :目的变址寄存器
IP(Instruction Pointer) :指令指针寄存器
段寄存器:
CS(Code Segment) :代码段寄存器
DS(Data Segment) :数据段寄存器
SS(Stack Segment) :堆栈段寄存器
ES(Extra Segment) :附加段寄存器
标志寄存器:
FR--flag register(程序状态字PSW--program status word),PSW常用的标志有:
标志 值为1时的标记 值为0时的标记 说明
OF(overflow flag) OV(overflow) NV(not overflow) 溢出标志 操作数超出机器能表示的范围表示溢出.溢出时为1.
ZF(zero flag) ZR(zero) NZ(not zero) 零标志 运算结果等于0时为1.否则为0.
PF(parity flag) PE(parity even) PO(parity odd) 奇偶标志 运算结果操作数位为1的个数为偶数个时为1.否则为0.
CF(carry flag) CY(carried) NC(not carried) 进位标志 最高有效位产生进位时为1.否则为0.
DF(direction flag) DN(down) UP(up) 方向标志 用于串处理.DF=1时.每次操作后使SIDI减小.DF=0时则增大.
SF(sign flag) NG(negtive) PL(plus) 符号标志 记录运算结果的符号.结果负时为1.
TF(trap flag) 陷阱标志 用于调试单步操作.
IF(interrupt flag) 中断标志 IF=1时.允许CPU响应可屏蔽中断.否则关闭中断.
AF(auxiliary flag) 辅助进位标志 运算时.第3位向第4位产生进位时为1.否则为0.

2、指令分类

2.1、数据传输指令

它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据。
1)、通用数据传送指令
MOV 传送字或字节。
MOVSX 先符号扩展,再传送。
MOVZX 先零扩展,再传送。
PUSH 把字压入堆栈。
POP 把字弹出堆栈。
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈。
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈。
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈。
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈。
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节。( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数。( 第二个操作数必须为累加器AL/AX/EAX )
XADD 先交换再累加。( 结果在第一个操作数里 )
XLAT 字节查表转换。
── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即
0-FFH); 返回 AL 为查表结果。 ( [BX+AL]->AL )

2)、输入输出端口传送指令
IN I/O端口输入。 ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出。 ( 语法: OUT {端口号│DX},累加器 )
输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
其范围是 0-65535。

3)、 目的地址传送指令
LEA 装入有效地址。
例: LEA DX,string ;把偏移地址存到DX。
LDS 传送目标指针,把指针内容装入DS。
例: LDS SI,string ;把段地址:偏移地址存到DS:SI。
LES 传送目标指针,把指针内容装入ES。
例: LES DI,string ;把段地址:偏移地址存到ES:DI。
LFS 传送目标指针,把指针内容装入FS。
例: LFS DI,string ;把段地址:偏移地址存到FS:DI。
LGS 传送目标指针,把指针内容装入GS。
例: LGS DI,string ;把段地址:偏移地址存到GS:DI。
LSS 传送目标指针,把指针内容装入SS。
例: LSS DI,string ;把段地址:偏移地址存到SS:DI。

4)、 标志传送指令
LAHF 标志寄存器传送,把标志装入AH。
SAHF 标志寄存器传送,把AH内容装入标志寄存器。
PUSHF 标志入栈。
POPF 标志出栈。
PUSHD 32位标志入栈。
POPD 32位标志出栈。

2.2、算术运算指令

ADD 加法。
ADC 带进位加法。
INC 加 1。
AAA 加法的ASCII码调整。
DAA 加法的十进制调整。
SUB 减法。
SBB 带借位减法。
DEC 减 1。
NEC 求反(以 0 减之)。
CMP 比较。(两操作数作减法,仅修改标志位,不回送结果)。
AAS 减法的ASCII码调整。
DAS 减法的十进制调整。
MUL 无符号乘法。
IMUL 整数乘法。
以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整。
DIV 无符号除法。
IDIV 整数除法。
以上两条,结果回送:
商回送AL,余数回送AH, (字节运算);
或 商回送AX,余数回送DX, (字运算)。
AAD 除法的ASCII码调整。
CBW 字节转换为字。 (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字。 (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字。 (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展。 (把EAX中的字的符号扩展到EDX中去)

2.3、逻辑运算指令

AND 与运算。
OR 或运算。
XOR 异或运算。
NOT 取反。
TEST 测试。(两操作数作与运算,仅修改标志位,不回送结果)。
SHL 逻辑左移。
SAL 算术左移。(=SHL)
SHR 逻辑右移。
SAR 算术右移。(=SHR)
ROL 循环左移。
ROR 循环右移。
RCL 通过进位的循环左移。
RCR 通过进位的循环右移。
以上八种移位指令,其移位次数可达255次。
移位一次时, 可直接用操作码。 如 SHL AX,1。
移位>1次时, 则由寄存器CL给出移位次数。
如 MOV CL,04
SHL AX,CL

2.4、串指令

DS:SI 源串段寄存器 :源串变址。
ES:DI 目标串段寄存器:目标串变址。
CX 重复次数计数器。
AL/AX 扫描值。
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量。
Z标志 用来控制扫描或比较操作的结束。
MOVS 串传送。
( MOVSB 传送字符。 MOVSW 传送字。 MOVSD 传送双字。 )
CMPS 串比较。
( CMPSB 比较字符。 CMPSW 比较字。 )
SCAS 串扫描。
把AL或AX的内容与目标串作比较,比较结果反映在标志位。
LODS 装入串。
把源串中的元素(字或字节)逐一装入AL或AX中。
( LODSB 传送字符。 LODSW 传送字。 LODSD 传送双字。 )
STOS 保存串。
是LODS的逆过程。
REP 当CX/ECX<>0时重复。
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复。
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复。
REPC 当CF=1且CX/ECX<>0时重复。
REPNC 当CF=0且CX/ECX<>0时重复。

2.5、程序转移指令

1)、无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF过程返回。

2)、条件转移指令 (短转移,-128到+127的距离内)
( 当且仅当(SF XOR OF)=1时,OP1 JA/JNBE 不小于或不等于时转移。
JAE/JNB 大于或等于转移。
JB/JNAE 小于转移。
JBE/JNA 小于或等于转移。
以上四条,测试无符号整数运算的结果(标志C和Z)。
JG/JNLE 大于转移。
JGE/JNL 大于或等于转移。
JL/JNGE 小于转移。
JLE/JNG 小于或等于转移。
以上四条,测试带符号整数运算的结果(标志S,O和Z)。
JE/JZ 等于转移。
JNE/JNZ 不等于时转移。
JC 有进位时转移。
JNC 无进位时转移。
JNO 不溢出时转移。
JNP/JPO 奇偶性为奇数时转移。
JNS 符号位为 “0” 时转移。
JO 溢出转移。
JP/JPE 奇偶性为偶数时转移。
JS 符号位为 “1” 时转移。

3)、循环控制指令(短转移)
LOOP CX不为零时循环。
LOOPE/LOOPZ CX不为零且标志Z=1时循环。
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环。
JCXZ CX为零时转移。
JECXZ ECX为零时转移。

4)、中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回

5)、处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续。
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态。
ESC 转换到外处理器。
LOCK 封锁总线。
NOP 空操作。
STC 置进位标志位。
CLC 清进位标志位。
CMC 进位标志取反。
STD 置方向标志位。
CLD 清方向标志位。
STI 置中断允许位。
CLI 清中断允许位。

2.6、伪指令

DW 定义字(2字节)。
PROC 定义过程。
ENDP 过程结束。
SEGMENT 定义段。
ASSUME 建立段寄存器寻址。
ENDS 段结束。
END 程序结束。

3、指令详解

指令 使用介绍 补充说明
AAA 未组合的十进制加法调整指令 AAA(ASCII Adgust for Addition) 格式: AAA 功能: 对两个组合的十进制数相加运算(存在AL中)的结果进行调整,产生一个未组合的十进制数放在AX中. 说明: 1. 组合的十进制数和未组合的十进制数:在计算中,十进制数可用四位二进制数编码,称为BCD码. 当一个节(8位)中存放一位BCD码,且放在字节的低4位, 高4位为时称为未组合的BCD码. 2. AAA的调整操作 若(AL) and 0FH>9 或 AF=1,则调整如下: (AL)<–(AL)+6,(AH)<–(AH)+1,AF=1,CF<–AF,(AL)<–(AL) and 0FH
AAD 未组合十进制数除法调整指令 AAD(ASCII Adjust for Division) 格式: AAD 功能: 在除法指令前对AX中的两个未组合十进制数进行调整,以便能用DIV指令实现两个未组合的十进制数的除法运算,其结果为未组合的十进制数,商(在AL中)和余数(在AH中). 说明: 1. AAD指令是在执行除法DIV之前使用的,以便得到二进制结果存于AL中,然后除以OPRD,得到的商在AL中,余数在AH中. 2. 示例: MOV BL,5 MOV AX,0308H AAD ;(AL)<–1EH+08H=26H,(AH)<--0 div bl ;商=07h-->(AL),余数=03H–>(AH).
AAM 未组合十进制数乘法调整指令 AAM(ASCII Adjust MULtiply) 格式: AAM 功能: 对两个未组合的十进制数相乘后存于AX中的结果进行调整,产生一个未组合的十进制数存在AL中. 说明: 1. 实际上是两个未组合的十进制数字节相乘,一个0~9的数与另一个0~9的数相乘其积最大为81.为了得到正确的结果,应进行如下调整: 乘积: (AH)<–(AL)/10 (AL)<–(AL)MOD10 2. 本指令应跟在MUL指令后使用,乘积的两位十进制结果,高位放在AH中,低位放在AL中.AH内容是MUL指令的结果被10除的商,即(AL)/10,而最后的AL内容是乘积被10整除的余数(即个位数).
AAS 未组合十进制减法调整指令 AAS(ASCII Adjust for Subtraction) 格式: AAS 功能: 对两个未组合十进制数相减后存于AL中的结果进行调整,调整后产生一个未组合的十进制数数且仍存于AL中. 说明: 1. 本指令影响标志位CF及AF. 2. 调整操作 若(AL) and 0FH > 9 或 AF=1 则(AL)<–(AL)-6,(AH)<–(AH)-1,CF<–AF,(AL)<–(AL) and 0FH, 否则(AL)<–(AL) and 0FH
ADC 带进位加法指令 ADC(Addition Carry) 格式: ADC OPRD1,OPRD2 功能: OPRD1<–OPRD1 + OPRD2 + CF 说明: 1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数. OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数. 2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的,但不允许两个都是存储器操作数. 3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志. 4. 该指令对标志位的影响同ADD指令.
ADD 加法指令 ADD(Addition) 格式: ADD OPRD1,OPRD2 功能: 两数相加 说明: 1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数. OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数. 2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的, 但不允许两个都是存储器操作数. 3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志.加法指令适用于无符号数或有符号数的加法运算.
AND 逻辑与运算指令 AND 格式: AND OPRD1,OPRD2 功能: 对两个操作数实现按位逻辑与运算,结果送至目的操作数.本指令可以进行字节或字的‘与’运算, OPRD1<–OPRD1 and OPRD2. 说明: 1. 目的操作数OPRD1为任一通用寄存器或存储器操作数.源操作数OPRD2为立即数,任一通用寄存器或存储器操作数. 2. 示例: AND AL,0FH ;(AL)<–(AL) AND 0FH AND AX,BX ;(AX)<–(AX) AND (BX) AND DX,BUFFER[SI+BX] AND BETA[BX],00FFH 注意: 两数相与,有一个数假则值为假
CALL 过程调用指令 CALL 格式: CALL OPRD 功能: 过程调用指令 说明: 1. 其中OPRD为过程的目的地址. 2. 过程调用可分为段内调用和段间调用两种.寻址方式也可以分为直接寻址和间接寻址两种. 3. 本指令不影响标志位.
CBW 字节扩展指令 CBW(Convert Byte to Word) 格式: CBW 功能: 将字节扩展为字,即把AL寄存器的符号位扩展到AH中. 说明: 1. 两个字节相除时,先使用本指令形成一个双字节长的被除数. 2. 本指令不影响标志位. 3. 示例: MOV AL,25 CBW IDIV BYTE PTR DATA1
CLC 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
CLD 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
CLI 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
CMC 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
CMP 比效指令 CMP(CoMPare) 格式: CMP OPRD1,OPRD2 功能: 对两数进行相减,进行比较. 说明: 1. OPRD1为任意通用寄存器或存储器操作数. OPRD2为任意通用寄存器或存储器操作数,立即数也可用作源操作数OPRD2. 2. 对标志位的影响同SUB指令,完成的操作与SUB指令类似,唯一的区别是不将OPRD1-OPRD2的结果送回OPRD1,而只是比较. 3. 在8088/8086指令系统中,专门提供了一组根据带符号数比较大小后,实现条件转移的指令.
CMPS 字符串比较指令 格式: CMPS OPRD1,OPRD2 CMPSB CMPSW 功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身. 同时SI,DI将自动调整. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较. 3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.
CMPSB 字符串比较指令 格式: CMPS OPRD1,OPRD2 CMPSB CMPSW 功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身. 同时SI,DI将自动调整. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较. 3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.
CMPSW 字符串比较指令 格式: CMPS OPRD1,OPRD2 CMPSB CMPSW 功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身. 同时SI,DI将自动调整. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较. 3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.
CWD 字扩展指令 CWD(Convert Word to Double Word) 格式: CWD 功能: 将字扩展为双字长,即把AX寄存器的符号位扩展到DX中. 说明: 1. 两个字或字节相除时,先用本指令形成一个双字长的的被除数. 2. 本指令不影响标志位. 3. 示例: 在B1、B2、B3字节类型变量中,分别存有8们带符号数a、b、c,实现(a*b+c)/a运算。
DAA 组合的十进制加法调整指令 DAA(Decimal Adjust for Addition) 格式: DAA 功能: 对AL中的两个组合进制数相加的结果进行调整,调整结果仍放在AL中,进位标志放在CF中. 说明: 1. 调整操作如下 (1) 若(AL) and 0FH>9 或 AF=1,则(AL)<–(AL)+6,AF<–1,对低四位的调整. (2) 若(AL) and 0F0H>90H 或 CF=1,则(AL)<–(AL)+60H,CF<–1. 2. 示例: (AL)=18H,(BL)=06H ADD AL,BL ; (AL)<–(AL)+(BL) ; (AL)=1EH DAA ; (AL)
DAS 组合十进制减法调整指令 DAS(Decimal Adjust for Subtraction) 格式: DAS 功能: 对两个组合十进制数相减后存于AL中的结果进行调整,调整后产生一个组合的十进制数且仍存于AL中. 说明: 调整操作 若(AL) and 0FH > 9 或 AF=1,则(AL)<–(AL)-6,AF=1 若(AL) and 0F0H > 90H 或 CF=1,则(AL)<–(AL)-60,CF=1
DEC 减一指令 DEC(Decrement by 1) 格式: DEC OPRD 功能: OPRD<–OPRD-1 说明: 1. OPRD 为寄存器或存储器操作数. 2. 这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位. 3. 示例 DEC AX DEC CL DEC WORD PTR[DI] DEC ALFA[DI+BX]
DIV 无符号数除法指令 DIV(DIVision) 格式: DIV OPRD 功能: 实现两个无符号二进制数除法运算. 说明: 1. 其中OPRD为任一个通用寄存器或存储器操作数. 2. 字节相除,被除数在AX中;字相除,被除数在DX,AX中,除数在OPRD中. 字节除法: (AL)<–(AX)/OPRD,(AH)<–(AX)MOD OPRD 字除法: (AX)<–(DX)(AX)/OPRD,(DX)<–(DX)(AX) MOD OPRD
ESC 处理器交权指令 ESC 格式: ESC EXTOPRD,OPRD 功能: 使用本指令可以实现协处理器出放在ESC指令代码中的6位常数,该常数指明协处理器要完成的功能. 当源操作数为存储器变量时,则取出该存储器操作数传送给协处理器. 说明: 1. 其中EXTOPRD为外部操作码,OPRD为源操作数. 2. 本指不影响标志位.
HLT 处理器暂停指令 HLT 格式: HLT 功能: 使处理器处于暂时停机状态. 说明: 1. 本指令不影响标志位. 2. 由执行HLT引起的暂停,只有RESET(复位)、NMI(非屏蔽中断请求)、INTR(可屏蔽的外部中断请求)信号可以使 其退出暂停状态.它可用于等待中断的到来或多机系统的同步操作.
IDIV 带符号数除法指定 IDIV(Interger DIVision) 格式: IDIV OPRD 功能: 这实现两个带符号数的二进制除法运算. 说明: 1. 其中OPRD为任一通用寄存器或存储器操作数. 2. 理由与IMUL相同,只有IDIV指令,才能得到符号数相除的正确结果. 3. 当被除数为8位,在进行字节除法前,应把AL的符号位扩充至AH中.在16位除法时,若被除数为16位,则应将AX中的符号位扩到DX中.
IMUL 带符号数乘法指令 IMUL(Integer MULtiply) 格式: IMUL OPRD 功能: 完成两个带符号数的相乘 说明: 1. 其中OPRD为任一通用寄存器或存储器操作数. 2. MUL指令对带符号相乘时,不能得到正确的结果. 例如: (AL)=255 (CL)=255 MUL CL (AX)=65025 注意: 这对无符号数讲,结果是正确的,但对带符号数讲,相当于(-1)*(-1)结果应为+1,而65025对应的带符号数为-511,显然是不正确的.
IN 输入指令 IN 格式: IN AL,n ;(AL)<–(n) IN AX,n ;(AX)<–(n+1),(n) IN AL,DX ;(AL)<–[(DX)] IN AX,DX ;(AX)<–[(DX)+1],[(DX)] 功能: 输入指令 说明: 1. 其中n为8位的端口地址,当字节输入时,将端口地址n+1的内容送至AH中,端口地址n的内容送AL中. 2. 端口地址也可以是16位的,但必须将16位的端口地址送入DX中.当字节寻址时,由DX内容作端口地址的内容送至AL中; 当输入数据字时,[(DX)+1]送AH,[(DX)]送AL中,用符号:(AX)<–[(DX)+1],[(DX)]表示.
INC 加1指令 INC(INCrement by 1) 格式: INC OPRD 功能: OPRD<–OPRD+1 说明: 1. OPRD 为寄存器或存储器操作数. 2. 这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位. 3. 示例: INC SI;(SI)<–(SI)+1 INC WORD PTR[BX] INC BYTE PTR[BX+DI] INC CL;(CL)<–(CL)+1 注意: 上述第二,三两条指令,是对存储字及存储字节的内容加1以替代原来的内容.
INT 软中断指令 INT 格式: INT n 其中n为软中断的类型号. 功能: 本指令将产生一个软中断,把控制转向一个类型号为n的软中断,该中断处理程序入口地址在中断向量表的n*4地址 处的二个存储器字(4个单元)中. 说明: 操作过程与INTO指令雷同,只需将10H改为n*4即可.所以,本指令也将影响标志位IF及TF.
INTO 溢出中断指令 INTO(INTerrupt if Overflow) 格式: INTO 功能: 本指令检测OF标志位,当OF=1时,说明已发生溢出,立即产生一个中断类型4的中断,当OF=0时,本指令不起作用. 说明: 1. 本指令影响标志位IF及TF. 2. 本指令可用于溢出处理,当OF=1时,产生一个类型4的软中断.在中断处理程序中完成溢出的处理操作.
IRET 中断返回指令 IRET 格式: IRET 功能: 用于中断处理程序中,从中断程序的断点处返回,继续执行原程序. 说明: 1. 本指令将影响所有标志位. 2. 无论是软中断,还是硬中断,本指令均可使其返回到中断程序的断点处继续执行原程序.
JA 条件转移指令JA/JNBE 格式: JA/JNBE标号 功能: 为高于/不低于等于的转移指令 说明: 1. 例如两个符号数a,b比较时,a>b(即CF=0,ZF=0)时转移.因为单一标志位CF=0,只表示a>=b. 2. JA/JNBE是同一条指令的两种不同的助记符. 3. 该指令用于无符号数进行条件转移
JAE 条件转移指令JAE/JNB 格式: JAE/JNB 标号 功能: 为高于等于/不低于的转移指令 说明: 1. JAE/JNB是同一条指令的两种不同的助记符. 2. 该指令用于无符号数进行条件转移.
JB 条件转移指令JB/JNAE 格式: JB/JNAE 标号 功能: 低于/不高于等于时转移 说明: 该指令用于无符号数的条件转移
JBE 条件转移指令JBE/JNA 格式: JBE/JNA 标号 功能: 低于等于/不高于时转移 说明: 该指令用于无符号数的条件转移
JC 条件转移指令 JC 格式: JC 标号 功能: CF=1,转至标号处执行 说明: JC为根据标志位CF进行转移的指令
JE 条件转移指令JE/JZ 格式: JE/JZ标号 功能: ZF=1,转至标号处执 说明: 1. 指令JE与JZ等价,它们是根据标志位ZF进行转移的指令 2. JE,JZ均为一条指令的两种助记符表示方法
JG 条件转移指令JG/JNLE 格式: JG/JNLE 标号 功能: 大于/不小于等于时转移 说明: 用于带符号数的条件转移指令
JGE 条件转移指令JGE/JNL 格式: JGE/JNL标号 功能: 大于等于/不小于时转移 说明: 用于带符号数的条件转移指令
JL 条件转移指令JL/JNGE 格式: JL/JNGE标号 功能: 小于/不大于等于时转移 说明: 用于带符号数的条件转移指令
JLE 条件转移指令JLE/JNG 格式: JLE/JNG 标号 功能: 小于等于/不大于时转移 说明: 用于带符号数的条件转移指令
JMP 无条件转移指令JMP 格式: JMP OPRD 功能: JMP指令将无条件地控制程序转移到目的地址去执行.当目的地址仍在同一个代码段内,称为段内转移;当目标地址不在同一个代码段内,则称为段间转移.这两种情况都将产生不同的指令代码,以便能正确地生成目的地址,在段内转移时,指令只要能提供目的地址的段内偏移量即够了;而在段间转移时,指令应能提供目的地址的段地址及段内偏移地址值. 说明: 1. 其中OPRD为转移的目的地址.程序转移到目的地址所指向的指令继续往下执行. 2. 本组指令对标志位无影响. 3. <1> 段内直接转移指令: JMP NEAR 标号 <2> 段内间接转移指令: JMP OPRD <3> 段间直接转移指令: JMP FAR 标号 <4> 段间间接转移指令:JMP OPRD其中的OPRD为存储器双字操作数.段间间接转移只能通过存储器操作数来实现.
JNA 条件转移指令JBE/JNA 格式: JBE/JNA 标号 功能: 低于等于/不高于时转移 说明: 该指令用于无符号数的条件转移
JNAE 条件转移指令JB/JNAE 格式: JB/JNAE 标号 功能: 低于/不高于等于时转移 说明: 该指令用于无符号数的条件转移
JNB 条件转移指令JAE/JNB 格式: JAE/JNB 标号 功能: 为高于等于/不低于的转移指令 说明: 1. JAE/JNB是同一条指令的两种不同的助记符. 2. 该指令用于无符号数进行条件转移.
JNBE 条件转移指令JA/JNBE 格式: JA/JNBE标号 功能: 为高于/不低于等于的转移指令 说明: 1. 例如两个符号数a,b比较时,a>b(即CF=0,ZF=0)时转移.因为单一标志位CF=0,只表示a>=b. 2. JA/JNBE是同一条指令的两种不同的助记符. 3. 该指令用于无符号数进行条件转移
JNC 条件转移指令JNC 格式: JNC标号 功能: CF=0,转至标号处执行 说明: JNC为根据标志位CF进行转移的指令
JNE 条件转移指令JNE/JNZ 格式: JNE/JNZ 标号 功能: ZF=0,转至标号处执行 说明: 1. 指令JNE与JNZ等价,它们是根据标志位ZF进行转移的指令 2. JNE,JNZ均为一条指令的两种助记符表示方法
JNG 条件转移指令JLE/JNG 格式: JLE/JNG 标号 功能: 小于等于/不大于时转移 说明: 用于带符号数的条件转移指令
JNGE 条件转移指令JL/JNGE 格式: JL/JNGE标号 功能: 小于/不大于等于时转移 说明: 用于带符号数的条件转移指令
JNL 条件转移指令JGE/JNL 格式: JGE/JNL标号 功能: 大于等于/不小于时转移 说明: 用于带符号数的条件转移指令
JNLE 条件转移指令JG/JNLE 格式: JG/JNLE 标号 功能: 大于/不小于等于时转移 说明: 用于带符号数的条件转移指令
JNO 条件转移指令JNO 格式: JNO 标号 功能: OF=0,转至标号处执行 说明: JNO是根椐溢出标志位OF进行转移的指令
JNP 条件转移指令JNP/JPO 格式: JNP/JPO 标号 功能: PF=0,转至标号处执行 说明: 1. 指令JNP与JPO,它们是根据奇偶标志位PF进行转移的指令 2. JNP,JPO均为一条指令的两种助记符表示方法
JNS 条件转移指令JNS 格式: JNS 标号 功能: SF=0,转至标号处执行 说明: JNS是根据符号标志位SF进行转移的指令
JNZ 条件转移指令JNE/JNZ 格式: JNE/JNZ 标号 功能: ZF=0,转至标号处执行 说明: 1. 指令JNE与JNZ等价,它们是根据标志位ZF进行转移的指令 2. JNE,JNZ均为一条指令的两种助记符表示方法
JO 条件转移指令JO 格式: JO 标号 功能: OF=1,转至标号处执行 说明: JO是根椐溢出标志位OF进行转移的指令
JP 条件转移指令JP/JPE 格式: JP/JPE 标号 功能: PF=1,转至标号处执行 说明: 1. 指令JP与JPE,它们是根据奇偶标志位PF进行转移的指令 2. JP,JPE均为一条指令的两种助记符表示方法
JPE 条件转移指令JP/JPE 格式: JP/JPE 标号 功能: PF=1,转至标号处执行 说明: 1. 指令JP与JPE,它们是根据奇偶标志位PF进行转移的指令 2. JP,JPE均为一条指令的两种助记符表示方法
JPO 条件转移指令JNP/JPO 格式: JNP/JPO 标号 功能: PF=0,转至标号处执行 说明: 1. 指令JNP与JPO,它们是根据奇偶标志位PF进行转移的指令 2. JNP,JPO均为一条指令的两种助记符表示方法
JS 条件转移指令JS 格式: JS 标号 功能: SF=1,转至标号处执行 说明: JS是根据符号标志位SF进行转移的指令
JZ 条件转移指令JE/JZ 格式: JE/JZ标号 功能: ZF=1,转至标号处执 说明: 1. 指令JE与JZ等价,它们是根据标志位ZF进行转移的指令 2. JE,JZ均为一条指令的两种助记符表示方法
LAHF 标志传送指令 LAHF 格式: LAHF 功能: 取FLAG标志寄存器低8位至AH寄存器.(AH)<–(FLAG)7~0 说明: 该指令不影响FLAG的原来内容,AH只是复制了原FLAG的低8位内容.
LDS 从存储器取出32位地址的指令 LDS 格式: LDS OPRD1,OPRD2 功能: 从存储器取出32位地址的指令. 说明: OPRD1 为任意一个16位的寄存器. OPRD2 为32位的存储器地址. 示例: LDS SI,ABCD LDS BX,FAST[SI] LDS DI,[BX] 注意: 上面LDS DI,[BX]指令的功能是把BX所指的32位地址指针的段地址送入DS,偏移地址送入DI.
LEA 有效地址传送指令 LEA 格式: LEA OPRD1,OPRD2 功能: 将源操作数给出的有效地址传送到指定的的寄存器中. 说明: 1. OPRD1 为目的操作数,可为任意一个16位的通用寄存器. OPRD2 为源操作数,可为变量名、标号或地址表达式. 示例: LEA BX,DATA1 LEA DX,BETA[BX+SI] LEA BX BX,[BP],[DI] 2. 本指令对标志位无影响。
LES 从存储器取出32位地址的指令 LES 格式: LES OPRD1,OPRD2 功能: 从存储器取出32位地址的指令. 说明: OPRD1 为任意一个16位的寄存器. OPRD2 为32位的存储器地址. 示例: LES SI,ABCD LES BX,FAST[SI] LES DI,[BX] 注意: 上面LES DI,[BX]指令的功能是把BX所指的32位地址指针的段地址送入ES,偏移地址送入DI.
LOCK 封锁总线指令 LOCK 格式: LOCK 功能: 指令是一个前缀,可放在指令的前面,告诉CPU在执行该指令时,不允许其它设备对总线进行访问. 无可用信息!用户可自行添加!
LODS 取字符串元素指令 LODS 格式: LODS OPRD 其中OPRD为源字符串符号地址. 功能: 把SI寻址的源串的数据字节送AL或数据字送AX中去, 并根据DF的值修改地址指针SI进行自动调整. 说明: 1. 本指令不影响标志位. 2. 当不使用操作数时,可用LODS(字节串)或LODSW(字串)指令.
LOOP 循环控制指令LOOP 格式: LOOP 标号 功能: (CX)<–(CX)-1,(CX)<>0,则转移至标号处循环执行, 直至(CX)=0,继续执行后继指令. 说明: 1. 本指令是用CX寄存器作为计数器,来控制程序的循环. 2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.
LOOPE 循环控制指令LOOPZ/LOOPE 格式: LOOPZ/LOOPE 标号 功能: (CX)<–(CX)-1,(CX)<>0 且ZF=1时,转至标号处循环 说明: 1. 本指令是用CX寄存器作为计数器,来控制程序的循环. 2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内. 3. 以上两种助记符等价.
LOOPNE 循环控制指令LOOPNZ/LOOPNE 格式: LOOPNZ/LOOPNE 标号 功能: (CX)<–(CX)-1,(CX)<>0 且ZF=0时,转至标号处循环 说明: 1. 本指令是用CX寄存器作为计数器,来控制程序的循环. 2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内. 3. 以上两种助记符等价.
LOOPNZ 循环控制指令LOOPNZ/LOOPNE 格式: LOOPNZ/LOOPNE 标号 功能: (CX)<–(CX)-1,(CX)<>0 且ZF=0时,转至标号处循环 说明: 1. 本指令是用CX寄存器作为计数器,来控制程序的循环. 2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内. 3. 以上两种助记符等价.
LOOPZ 循环控制指令LOOPZ/LOOPE 格式: LOOPZ/LOOPE 标号 功能: (CX)<–(CX)-1,(CX)<>0 且ZF=1时,转至标号处循环 说明: 1. 本指令是用CX寄存器作为计数器,来控制程序的循环. 2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内. 3. 以上两种助记符等价.
MOVE 数据传送指令 MOV 格式: MOV OPRD1,OPRD2 功能: 本指令将一个源操作数送到目的操作数中,即OPRD1<–OPRD2. 说明: 1. OPRD1 为目的操作数,可以是寄存器、存储器、累加器. OPRD2 为源操作数,可以是寄存器、存储器、累加器和立即数. 2. MOV 指令以分为以下四种情况: <1> 寄存器与寄存器之间的数据传送指令 <2> 立即数到通用寄存器数据传送指令 <3> 寄存器与存储器之间的数据传送指令 <4> 立即数到存储器的数据传送 3. 本指令不影响状态标志位
MOVS 字符串传送指令 MOVS 格式: MOVS OPRD1,OPRD2 MOVSB MOVSW 功能: OPRD1<–OPRD2. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减. 3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,. 4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW. 5. 本指令不影响标志位.
MOVSB 字符串传送指令 MOVS 格式: MOVS OPRD1,OPRD2 MOVSB MOVSW 功能: OPRD1<–OPRD2. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减. 3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,. 4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW. 5. 本指令不影响标志位.
MOVSW 字符串传送指令 MOVS 格式: MOVS OPRD1,OPRD2 MOVSB MOVSW 功能: OPRD1<–OPRD2. 说明: 1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址. 2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减. 3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,. 4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW. 5. 本指令不影响标志位.
MUL 无符号数乘法指令 MUL(MULtiply) 格式: MUL OPRD 功能: 乘法操作. 说明: 1. OPRD为通用寄存器或存储器操作数. 2. OPRD为源操作数,即作乘数.目的操作数是隐含的,即被乘数总是指定为累加器AX或AL的内容. 3. 16位乘法时,AX中为被乘数.8位乘法时,AL为被乘数.当16位乘法时,32位的乘积存于DX及AX中;8位乘法的16位乘积存于AX中. 4. 操作过程: 字节相乘:(AX)<–(AL)*OPRD,当结果的高位字节(AH)不等于0时,则CF=1、OF=1.
NEG 取补指令 NEG(NEGate) 格式: NEG OPRD 功能: 对操作数OPRD进行取补操作,然后将结果送回OPRD.取补操作也叫作求补操作,就是求一个数的相反数的补码. 说明: 1. OPRD为任意通用寄存器或存储器操作数. 2. 示例: (AL)=44H,取补后,(AL)=0BCH(-44H). 3. 本指令影响标志位CF、OF、SF、PF、ZF及AF.
NOP 空操作指令 NOP 格式: NOP 功能: 本指令不产生任何结果,仅消耗几个时钟周期的时间,接着执行后续指令,常用于程序的延时等. 说明: 本指令不影响标志位.
NOT 逻辑非运算指令 NOT 格式: NOT OPRD 功能: 完成对操作数按位求反运算(即0变1,1变0),结果关回原操作数. 说明: 1. 其中OPRD可为任一通用寄存器或存储器操作数. 2. 本指梳令可以进行字或字节‘非’运算. 3. 本指令不影响标志位.
OR 逻辑或指令 OR 格式: OR OPRD1,OPRD2 功能: OR指令完成对两个操作数按位的‘或’运算,结果送至目的操作数中,本指令可以进行字节或字的‘或’运算. OPRD1<–OPRD1 OR OPRD2. 说明: 1. 其中OPRD1,OPRD2含义与AND指令相同,对标志位的影响也与AND指令相同. 2. 两数相或,有一个数为真则值为真.
OUT 输出指令 OUT 格式: OUT n,AL ;(n)<–(AL) 功能: 输出指令 说明: 1. OUT n,AX ;(n+1),(n)<–(AX) OUT DX,AL ;[(DX)]<–(AL) OUT DX,AX ;[(DX)+1],[(DX)]<–(AX) 2. 输入指令及输出指令对标志位都不影响.
POP 堆栈操作指令 PUSH和POP 格式: PUSH OPRD POP OPRD 功能: 实现压入操作的指令是PUSH指令;实现弹出操作的指令是POP指令. 说明: 1. OPRD为16位(字)操作数,可以是寄存器或存储器操作数. 2. POP指令的操作过程是: POP OPRD:OPRD<–((SP)),(SP)<–(SP)+2 它与压入操作相反,是先弹出栈顶的数顶,然后再修改指针SP的内容. 3. 示例: POP AX POP DS POP DATA1 POP ALFA[BX][DI] 4. PUSH和POP指令对状态标志位没有影响.
POPF 标志传送指令 POPF 格式: POPF 功能: 本指令的功能与PUSHF相反,在子程序调用和中断服务程序中,往往用PUSHF指令保护FLAG的内容,用POPF指令将保护的FLAG内容恢复. 说明: 如果对堆栈中的原FLAG内容进行修改,如对TF等标志位进行修改,然后再弹回标志位寄存器FLAG.这是通过指令修改TF标志的唯一方法.
PUSH 堆栈操作指令 PUSH和POP 格式: PUSH OPRD POP OPRD 功能: 实现压入操作的指令是PUSH指令;实现弹出操作的指令是POP指令. 说明: 1. OPRD为16位(字)操作数,可以是寄存器或存储器操作数. 2. PUSH的操作过程是: (SP)<–(SP)-2,((sp))<–OPRD 即先修改堆栈指针SP(压入时为自动减2),然后,将指定的操作数送入新的栈顶位置. 此处的((SP))<–OPRD,也可以理解为: [(SS)*16+(SP)]<–OPRD 或 [SS:SP]<–OPRD
PUSHF 标志传送指令 PUSHF 格式: PUSHF 功能: 本指令可以把标志寄存器的内容保存到堆栈中去
RCL 循环移位指令 格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令. ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令. RCL OPRD1,COUNT ;带进位的左循环移位指令. RCR OPRD1,COUNT ;带进位的右循环移位指令. 说明: 1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1. 2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入, 所以可以利用它实现多字节的循环.
RCR 循环移位指令 格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令. ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令. RCL OPRD1,COUNT ;带进位的左循环移位指令. RCR OPRD1,COUNT ;带进位的右循环移位指令. 说明: 1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1. 2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入,所以可以利用它实现多字节的循环. 注意: 以上程序中的指令SHR AL,CL如改为SAR AL,CL,虽然最高4位可移入低4位,但最高位不为0,故应加入一条指令AND AL,0FH.否则,若最高位不为0时,将得到错误结果.
REP 重复前缀的说明 格式: REP ;CX<>0 重复执行字符串指令 REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令 REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令 功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中. 说明: 1. REP与MOVS或STOS串操作指令相结合使用,完成一组字符的传送或建立一组相同数据的字符串. 2. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较. 3. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字. 4. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.
REPE 重复前缀的说明 格式: REP ;CX<>0 重复执行字符串指令 REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令 REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令 功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中. 说明: 1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较. 2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字. 3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令. 4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.
REPNE 重复前缀的说明 格式: REP ;CX<>0 重复执行字符串指令 REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令 REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令 说明: 1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较. 2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字. 3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令. 4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.
REPNZ 重复前缀的说明 格式: REP ;CX<>0 重复执行字符串指令 REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令 REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令 说明: 1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较. 2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字. 3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令. 4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.
REPZ 重复前缀的说明 格式: REP ;CX<>0 重复执行字符串指令 REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令 REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令 功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中. 说明: 1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较. 2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字. 3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令. 4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.
RET 返回指令 RET 格式: RET 功能: 当调用的过程结束后实现从过程返回至原调用程序的下一条指令,本指令不影响标志位. 说明: 由于在过程定义时,已指明其近(NEAR)或远(FAR)的属性,所以RET指令根据段内调用与段间调用,执行不同的操作 对段内调用: 返回时,由堆栈弹出一个字的返回地址的段内偏移量至IP. 对段外调用: 返回时,由堆栈弹出的第一个字为返回地址的段内偏移量,将其送入IP中,由堆栈弹出第二个字为返回地址的段基址,将其送入CS中.
ROL 循环移位指令 格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令. ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令. RCL OPRD1,COUNT ;带进位的左循环移位指令. RCR OPRD1,COUNT ;带进位的右循环移位指令. 说明: 1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1. 2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入, 所以可以利用它实现多字节的循环.
ROR 循环移位指令 格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令. ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令. RCL OPRD1,COUNT ;带进位的左循环移位指令. RCR OPRD1,COUNT ;带进位的右循环移位指令. 说明: 1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1. 2. 由于循环移位,所以对字节移位8次; 对字移位16次,可恢复为原操作数.
SAHF 标志传送指令 SAHF 格式: SAHF 功能: 将AH存至FLAG低8位 说明: 本指令将用AH的内容改写FLAG标志寄存器中的SF、ZF、AF、PF、和CF标志,从而改变原来的标志位.
SAL 算术左移指令 SAL(Shift Arithmetic Left) 格式: SAL OPRD1,COUNT 功能: 其中OPRD1,COUNT与指令SHL相同.本指令与SHL的功能也完全相同,这是因为逻辑左移指令与算术左移指令所要完成的操作是一样的. 说明: 1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数. 2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.
SAR 算术右移指令 SAR 格式: SAR OPRD1,COUNT 功能: 本指令通常用于对带符号数减半的运算中,因而在每次右移时,保持最高位(符号位)不变,最低位右移至CF中. 说明: 1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数. 2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.
SBB 带借位减去指令 SBB(SuBtraction with Borrow) 格式: SBB OPRD1,OPRD2 功能: 是进行两个操作数的相减再减去CF进位标志位,即从OPRD1<–OPRD1-OPRD2-CF,其结果放在OPDR1中. 说明: 示例 SBB DX,CX SBB AX,DATA1 SBB BX,2000H SBB ALFA[BX+SI],SI SBB BETAP[DI,030AH
SCAS 字符串搜索指令 SCAS 格式: SCAS OPRD SCASB SCASW 功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身. 地址指针DI自动调整. 说明: 1. 其中OPRD为目的串符号地址. 2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前, 把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找. 指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.
SCASB 字符串搜索指令 SCAS 格式: SCAS OPRD SCASB SCASW 功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身. 地址指针DI自动调整. 说明: 1. 其中OPRD为目的串符号地址. 2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前, 把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找. 指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.
SCASW 字符串搜索指令 SCAS 格式: SCAS OPRD SCASB SCASW 功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身. 地址指针DI自动调整. 说明: 1. 其中OPRD为目的串符号地址. 2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前, 把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找. 指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.
SHL 逻辑左移指令 SHL(Shift logical left) 格式: SHL OPRD1,COUNT 功能: 对给定的目的操作数左移COUNT次,每次移位时最高位移入标志位CF中,最低位补零. 说明: 1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数. 2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数. 3. 例如: SHL AL,1 SHL CX,1 SHL ALFA[DI] 或者: MOV CL,3 SHL DX,CL SHL ALFA[DI],CL
SHR 逻辑右移指令 SHR 格式: SHR OPRD1,COUNT 功能: 本指令实现由COUNT决定次数的逻辑右移操作,每次移位时,最高位补0,最低位移至标志位CF中. 说明: 1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数. 2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数. 3. 影响标志位OF,PF,SF,ZF,CF.
STC 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
STD 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
STI 处理器控制指令-标志位操作指令 格式: CLC ;置CF=0 STC ;置CF=1 CMC ;置CF=(Not CF)进位标志求反 CLD ;置DF=0 STD ;置DF=1 CLI ;置IF=0,CPU禁止响应外部中断 STI ;置IF=1,使CPU允许向应外部中断 功能: 完成对标志位的置位、复位等操作. 说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.
STOS 字符串存储指令 STOS 格式: STOS OPRD 功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去.指针DI将根据DF的值进行自动调整. 说明: 1. 其中OPRD为目的串符号地址. 2. 本指令不影响标志位.当不使用操作数时,可用STOSB或STOSW分别表示字节串或字串的操作.
SUB 减法指令SUB(SUBtract) 格式: SUB OPRD1,OPRD2 功能: 两个操作数的相减,即从OPRD1中减去OPRD2,其结果放在OPDR1中. 说明: 示例 SUB DX,CX SUB [BX+25],AX SUB DI,ALFA[SI] SUB CL,20 SUB DATA1[DI][BX],20A5H
TEST 测试指令 TEST 格式: TEST OPRD1,OPRD2 功能: 其中OPRD1、OPRD2的含义同AND指令一样,也是对两个操作数进行按位的’与’运算,唯一不同之处是不将’与’的结 果送目的操作数,即本指令对两个操作数 的内容均不进行修改,仅是在逻辑与操作后,对标志位重新置位. 说明: TEST与AND指令的关系,有点类似于CMP与SUB指令之间的关系.
WAIT 处理器等待指令 WAIT 格式: WAIT 功能: 本指令将使处理器检测TEST端脚,当TEST有效时,则退出等待状态执行下条指令,否则处理器处于等待状态,直到TEST有效. 说明: 本指令不影响标志位.
XCHG 数据交换指令 XCHG 格式: XCHG OPRD1,OPRD2 其中的OPRD1为目的操作数,OPRD2为源操作数 功能: 将两个操作数相互交换位置,该指令把源操作数OPRD2与目的操数OPRD1交换. 说明: 1. OPRD1及OPRD2可为通用寄存器或存储器,但是两个存储器之间是不能用XCHG指令实现的. 2. 段寄存器内容不能用XCHG指令来交换. 3. 若要实现两个存储器操作数DATA1及DATA2的交换,可用以下指令实现: 示例: PUSH DATA1 PUSH DATA2 POP DATA1 POP DATA2 4. 本指令不影响状态标志位.
XLAT 查表指令 XLAT 格式: XLAT TABLE其中TABLE为一待查表格的首地址. 功能: 把待查表格的一个字节内容送到AL累加器中. 说明: 1. 在执行该指令前,应将TABLE先送至BX寄存器中,然后将待查字节与在表格中距表首地址位移量送AL,即 (AL)<–((BX)+(AL)). 2. 本指令不影响状态标位,表格长度不超过256字节.
XOR 逻辑异或运算指令 XOR 格式: XOR OPRD1,OPRD2 功能: 实现两个操作数按位‘异或’运算,结果送至目的操作数中. OPRD1<–OPRD1 XOR OPRD2 说明: 1. 其在OPRD1、OPRD2的含义与AND指令相同,对标志位的影响与与AND指令相同. 2. 相异为真,相同为假.

4、x86和amd64指令参考

AAA-添加后进行ASCII调整
AAD-ASCII分割前调整AX
AAM-ASCII调整AX后乘以
AAS-ASCII减法后调整AL
ADC-带进位加法
ADCX - 带进位标志的两个操作数的无符号整数相加
ADD-加
ADDPD-Add打包的双精度浮点值
ADDPS-Add打包的单精度浮点值
ADDSD-Add标量双精度浮点值
ADDSS - add标量单精度浮点值
ADDSUBPD-压缩双FP加/减
ADDSUBPS-压缩单FP加/减
ADOX - 带有溢出标志的两个操作数的无符号整数
AESDEC - 执行一轮AES解密流程
AESDECLAST - 执行AES解密流的最后一轮
AESENC - 执行一轮AES加密流程
AESENCLAST - 执行AES加密流的最后一轮
AESIMC - 执行AES InvMixColumn转换
AESKEYGENASSIST-AES轮回密钥生成辅助
AND-逻辑与
ANDN - 逻辑AND NOT
ANDPD-压缩双精度浮点值的按位逻辑与
ANDPS—压缩单精度浮点值的按位逻辑与
ANDNPD—压缩双精度浮点值的按位逻辑AND NOT
ANDNPS—压缩单精度浮点值的按位逻辑AND NOT
ARPL—调整段选择器的RPL字段
BLENDPD — 混合封装双精度浮点值
BEXTR — 位字段提取
BLENDPS — 混合封装的单精度浮点值
BLENDVPD — 可变混合封装双精度浮点值
BLENDVPS — 可变混合封装单精度浮点值
BLSI — 提取最低设置隔离位
BLSMSK — 获取掩码到最低设置位
BLSR — 复位最低设置位
BNDCL—检查下限
BNDCU/BNDCN—检查上边界
BNDLDX—使用地址转换加载扩展边界
BNDMK—制作界限
BNDMOV—移动边界
BNDSTX—使用地址转换存储扩展边界
BOUND—检查阵列索引对边界
BSF—位扫描转发
BSR—位扫描反转
BSWAP—字节交换
BT—位测试
BTC—位测试和补码
BTR—位测试和复位
BTS—位测试和设置
BZHI — 从指定位位置开始的零高位
CALL—调用过程
CBW/CWDE/CDQE—将字节转换为字/将字转换为双字/将双字转换为四字
CLAC—清除EFLAGS寄存器中的AC标志
CLC—清除进位标志
CLD—清除方向标志
CLFLUSH—刷新缓存行
CLFLUSHOPT—刷新缓存行已优化
CLI — 清除中断标志
CLTS—清除CR0中的任务切换标志
CLWB—高速缓存行回写
CMC—补充进位标志
CMOVcc—条件移动
CMP—比较两个操作数
CMPPD—比较打包的双精度浮点值
CMPPS—比较打包的单精度浮点值
CMPS/CMPSB/CMPSW/CMPSD/CMPSQ—比较字符串操作数
CMPSD—比较标量双精度浮点值
CMPSS—比较标量单精度浮点值
CMPXCHG—比较和交流
CMPXCHG8B/CMPXCHG16B—比较和交换字节
COMISD—比较标量有序双精度浮点值和设置EFLAGS
COMISS—比较标量有序单精度浮点值和设置EFLAGS
CPUID—CPU识别
CRC32 — 累加CRC32值
CVTDQ2PD—将打包的双字整数转换为打包的双精度浮点值
CVTDQ2PS—将打包的双字整数转换为打包的单精度浮点值
CVTPD2DQ—将打包的双精度浮点值转换为打包的双字整数
CVTPD2PI—将打包的双精度FP值转换为打包的双字整数
CVTPD2PS—将打包的双精度浮点值转换为打包的单精度浮点值
CVTPI2PD—将打包的双字整数转换为打包的双精度FP值
CVTPI2PS—将打包的双字整数转换为打包的单精度FP值
CVTPS2DQ—将打包的单精度浮点值转换为打包签名的双字整数值
CVTPS2PD—将打包的单精度浮点值转换为打包的双精度浮点值
CVTPS2PI—将打包的单精度FP值转换为打包的双字整数
CVTSD2SI—将标量双精度浮点值转换为双字整数
CVTSD2SS—将标量双精度浮点值转换为标量单精度浮点值
CVTSI2SD—将双字整数转换为标量双精度浮点值
CVTSI2SS—将双字整数转换为标量单精度浮点值
CVTSS2SD—将标量单精度浮点值转换为标量双精度浮点值
CVTSS2SI—将标量单精度浮点值转换为双字整数
CVTTPD2DQ—转换为截断打包的双精度浮点值到打包的双字整数
CVTTPD2PI—转换为截断打包的双精度FP值到打包的双字整数
CVTTPS2DQ—将截断转换为打包的单精度浮点值到打包签名的双字整数值
CVTTPS2PI—转换为截断打包的单精度FP值到打包的双字整数
CVTTSD2SI—将截断的标量双精度浮点值转换为有符号整数
CVTTSS2SI—将截断标量单精度浮点值转换为整数
CWD/CDQ/CQO—将字转换为双字/将双字转换为四字
DAA—十进制加法后调整AL
DAS—十进制减法后调整AL
DEC—减少1
DIV—无符号除法
DIVPD—除法包装的双精度浮点值
DIVPS—分割打包的单精度浮点值
DIVSD—除法标量双精度浮点值
DIVSS—除法标量单精度浮点值
DPPD — 封装双精度浮点值的点积
DPPS — 封装单精度浮点值的点积
EMMS—空MMX技术状态
ENTER—为过程参数创建堆栈框架
EXTRACTPS—提取打包的浮点值
F2XM1—计算2x-1
FABS—绝对值
FADD/FADDP/FIADD—Add
FBLD—加载二进制编码十进制
FBSTP—存储BCD整数和弹出
FCHS—更改标志
FCLEX/FNCLEX—清除例外
FCMOVcc—浮点条件移动
FCOM/FCOMP/FCOMPP—比较浮点值
FCOMI/FCOMIP/ FUCOMI/FUCOMIP—比较浮点值和设置EFLAGS
FCOS— 余弦
FDECSTP—减少堆栈顶指针
FDIV/FDIVP/FIDIV—划分
FDIVR/FDIVRP/FIDIVR—反向分割
FFREE—自由浮点寄存器
FICOM/FICOMP—比较整数
FILD—加载整数
FINCSTP—增加堆栈顶指针
FINIT/FNINIT—初始化浮点单元
FIST/FISTP—存储整数
FISTTP—存储整数与截断
FLD—加载浮点值
FLD1/FLDL2T/FLDL2E/FLDPI/FLDLG2/FLDLN2/FLDZ—负载常数
FLDCW—加载x87 FPU控制字
FLDENV—加载x87 FPU环境
FMUL/FMULP/FIMUL—乘
FNOP—无操作
FPATAN—部分反正切
FPREM—部分剩余
FPREM1—部分剩余
FPTAN—部分切线
FRNDINT—舍入为整数
FRSTOR—恢复x87 FPU状态
FSAVE/FNSAVE—存储x87 FPU状态
FSCALE—规模
FSIN—正弦
FSINCOS—正弦和余弦
FSQRT—平方根
FST/FSTP—存储浮点值
FSTCW/FNSTCW—存储x87 FPU控制字
FSTENV/FNSTENV—存储x87 FPU环境
FSTSW/FNSTSW—存储x87 FPU状态字
FSUB/FSUBP/FISUB—减去
FSUBR/FSUBRP/FISUBR—反向减
FTST—TEST
FUCOM/FUCOMP/FUCOMPP—无序比较浮点值
FXAM—检查浮点
FXCH—交换寄存器内容
FXRSTOR—恢复x87 FPU,MMX,XMM和MXCSR状态
FXSAVE—保存x87 FPU,MMX技术和SSE状态
FXTRACT—提取指数和指标
FYL2X—计算y log2x
FYL2XP1—计算y
log2(x + 1)
HADDPD—包装双FP水平添加
HADDPS—包装单FP水平添加
HLT—停
HSUBPD—压缩双FP水平减法
HSUBPS—打包单FP水平减法
IDIV—签名除法
IMUL—签名乘法
IN—从端口输入
INC—递增1
INS/INSB/INSW/INSD—从端口到字符串的输入
INSERTPS—插入标量单精度浮点值
INT n/INTO/INT 3—调用中断过程
INVD—无效内部缓存
INVLPG—使TLB条目无效
INVPCID—使过程上下文标识符无效
IRET/IRETD—中断返回
Jcc—如果条件满足则跳转
JMP—跳
KADDW/KADDB/KADDQ/KADDD—ADD两个面具
KANDW/KANDB/KANDQ/KANDD—按位逻辑和掩码
KANDNW/KANDNB/KANDNQ/KANDND—按位逻辑AND NOT掩码
KMOVW/KMOVB/KMOVQ/KMOVD—从和到掩码寄存器
KNOTW/KNOTB/KNOTQ/KNOTD—NOT屏蔽寄存器
KORW/KORB/KORQ/KORD—按位逻辑或掩码
KORTESTW/KORTESTB/KORTESTQ/KORTESTD—OR Masks And Set Flags
KSHIFTLW/KSHIFTLB/KSHIFTLQ/KSHIFTLD—移位左掩码寄存器
KSHIFTRW/KSHIFTRB/KSHIFTRQ/KSHIFTRD—Shift右掩码寄存器
KTESTW/KTESTB/KTESTQ/KTESTD—打包位测试掩码和设置标志
KUNPCKBW/KUNPCKWD/KUNPCKDQ—解包掩码寄存器
KXNORW/KXNORB/KXNORQ/KXNORD—按位逻辑XNOR掩码
KXORW/KXORB/KXORQ/KXORD—按位逻辑异或掩码
LAHF—将状态标志加载到AH寄存器中
LAR—加载访问权限字节
LDDQU—加载未对齐的整数128位
LDMXCSR—加载MXCSR寄存器
LDS/LES/LFS/LGS/LSS—加载远程指针
LEA—加载有效地址
LEAVE—高级过程退出
LFENCE—负载栅栏
LGDT/LIDT—加载全局/中断描述符表寄存器
LLDT—加载本地jubu描述符表寄存器
LMSW—加载机器状态字
LOCK—置位LOCK#信号前缀
LODS/LODSB/LODSW/LODSD/LODSQ—加载字符串
LOOP/LOOPcc—根据ECX计数器循环
LSL—负载段限制
LTR—加载任务寄存器
LZCNT— 计数前导零位的数量

MASKMOVDQU—存储双字双字的所选字节
MASKMOVQ—存储选定的四字节字节
MAXPD—最大打包双精度浮点值
MAXPS—最大打包单精度浮点值
MAXSD—返回最大标量双精度浮点值
MAXSS—返回最大标量单精度浮点值
MFENCE—内存围栏
MINPD—最小包装双精度浮点值
MINPS—最小打包单精度浮点值
MINSD—返回最小标量双精度浮点值
MINSS—返回最小标量单精度浮点值
MONITOR—设置监视器地址
MOV—移动
MOVAPD—移动对齐打包的双精度浮点值
MOVAPS—移动对齐打包的单精度浮点值
MOVBE—在交换字节后移动数据
MOVD/MOVQ—移动双字/移动四字
MOVDDUP—复制双精度浮点值
MOVDQA,VMOVDQA32/64—移动对齐的打包整数值
MOVDQU,VMOVDQU8/16/32/64—移动未对齐的打包整数值
MOVDQ2Q—将四字从XMM移动到MMX技术寄存器
MOVHLPS—将打包的单精度浮点值从高到低移动
MOVHPD—移动高压缩双精度浮点值
MOVHPS—移动高度封装的单精度浮点值
MOVLHPS—将打包的单精度浮点值从低到高移动
MOVLPD—移动低压缩双精度浮点值
MOVLPS—移动低压缩单精度浮点值
MOVMSKPD—提取封装的双精度浮点符号掩码
MOVMSKPS—提取打包的单精度浮点符号掩码
MOVNTDQA—加载双字体非时间对齐提示
MOVNTDQ—使用非时间提示存储打包的整数
MOVNTI—使用非时间提示存储双字
MOVNTPD—使用非时间提示存储打包的双精度浮点值
MOVNTPS—使用非时间提示存储打包的单精度浮点值
MOVNTQ—使用非时间提示的四字存储
MOVQ—移动四字
MOVQ2DQ—将四字从MMX技术移动到XMM寄存器
MOVS/MOVSB/MOVSW/MOVSD/MOVSQ—将数据从字符串移动到字符串
MOVSD—移动或合并标量双精度浮点值
MOVSHDUP—复制单个FP值
MOVSLDUP—复制单个FP值
MOVSS—移动或合并标量单精度浮点值
MOVSX/MOVSXD—使用符号扩展移动
MOVUPD—移动非对齐打包的双精度浮点值
MOVUPS—移动不对齐打包的单精度浮点值
MOVZX—用零扩展移动
MPSADBW — 计算多个封装的绝对差的和
MUL—无符号乘法
MULPD—乘法封装的双精度浮点值
MULPS—乘法封装的单精度浮点值
MULSD—乘以标量双精度浮点值
MULSS—乘以标量单精度浮点值
MULX — 无符号乘法不影响标志
MWAIT—监视等待
NEG—二的互补阴性
NOP—无操作
NOT—一个补码阴性
OR—逻辑包含OR
ORPD—压缩双精度浮点值的按位逻辑或
ORPS—压缩单精度浮点值的按位逻辑或
OUT—输出到端口
OUTS/OUTSB/OUTSW/OUTSD—输出字符串到端口
PABSB/PABSW/PABSD/PABSQ — 压缩绝对值
PACKSSWB/PACKSSDW—包含有符号饱和度
PACKUSDW—具有无符号饱和度的包
PACKUSWB—具有无符号饱和度的包
PADDB/PADDW/PADDD/PADDQ—添加打包的整数
PADDSB/PADDSW—添加带签名饱和度的打包签名整数
PADDUSB/PADDUSW—添加带有无符号饱和的打包的无符号整数
PALIGNR — 包装对齐
PAND—逻辑AND
PANDN—逻辑AND NOT
PAUSE—旋转环提示
PAVGB/PAVGW—平均打包整数
PBLENDVB — 可变混合打包字节
PBLENDW — 混合包装的词
PCLMULQDQ - 无载乘法四字
PCMPEQB/PCMPEQW/PCMPEQD— 比较打包数据以等于
PCMPEQQ — 比较打包的Qword数据
PCMPESTRI — 压缩比较显式长度字符串,返回索引
PCMPESTRM — 压缩比较显式长度字符串,返回掩码
PCMPGTB/PCMPGTW/PCMPGTD—比较打包签名的整数大于
PCMPGTQ — 比较打包数据大于
PCMPISTRI — 压缩比较隐式长度字符串,返回索引
PCMPISTRM — 压缩比较隐式长度字符串,返回掩码
PDEP — 平行位存款
PEXT — 平行位提取
PEXTRB/PEXTRD/PEXTRQ — 提取字节/双字/ Qword
PEXTRW—提取 Word
PHADDW/PHADDD — 包装水平添加
PHADDSW — 包装水平添加和饱和
PHMINPOSUW — 包装水平词最小
PHSUBW/PHSUBD — 打包水平减法
PHSUBSW — 包装水平扣除和饱和
PINSRB/PINSRD/PINSRQ — 插入字节/双字/ Qword
PINSRW—插入字
PMADDUBSW — 乘法和添加打包签名和无符号字节
PMADDWD—乘法和添加打包整数
PMAXSB/PMAXSW/PMAXSD/PMAXSQ—最大打包签名整数
PMAXUB/PMAXUW—最大打包的无符号整数
PMAXUD/PMAXUQ—最大打包的无符号整数
PMINSB/PMINSW—最小打包签名整数
PMINSD/PMINSQ—最小打包签名整数
PMINUB/PMINUW—最小打包的无符号整数
PMINUD/PMINUQ—最小打包的无符号整数
PMOVMSKB—移动字节掩码
PMOVSX—包装移动与符号扩展
PMOVZX—带零扩展的打包移动
PMULDQ—乘以压缩双字整数
PMULHRSW — 包装高与圆和规模
PMULHUW—乘法打包的无符号整数和存储高结果
PMULHW—乘法打包签名整数和存储高结果
PMULLD/PMULLQ—乘以压缩整数和存储低结果
PMULLW—乘以打包的有符号整数和存储低结果
PMULUDQ—乘法打包的无符号双字整数
POP—从堆栈中弹出一个值
POPA/POPAD—弹出所有通用寄存器
POPCNT — 返回设置为1的位数计数
POPF/POPFD/POPFQ—弹出堆栈到 EFLAGS 寄存器
POR—按位逻辑或
PREFETCHh—预取数据到缓存
PREFETCHW—在写入预期中将数据预取到缓存中
PREFETCHWT1—将向量数据预取到具有意图写入和T1提示的高速缓存中
PSADBW—计算绝对差的和
PSHUFB — 打包的随机字节
PSHUFD—随机打包双字
PSHUFHW—随机包装高字
PSHUFLW—随机包装低字
PSHUFW—随机包装的词
PSIGNB/PSIGNW/PSIGND — 打包标志
PSLLDQ—移位双四字左逻辑
PSLLW/PSLLD/PSLLQ—移位数据打包左逻辑
PSRAW/PSRAD/PSRAQ—移位打包数据右算术
PSRLDQ—移位双四字右逻辑
PSRLW/PSRLD/PSRLQ—移位打包数据右逻辑
PSUBB/PSUBW/PSUBD—减去打包的整数
PSUBQ—减去打包的四字整数
PSUBSB/PSUBSW—减去带有符号饱和的打包有符号整数
PSUBUSB/PSUBUSW—使用无符号饱和度减去打包的无符号整数
PTEST- 逻辑比较
PTWRITE - 将数据写入处理器跟踪数据包
PUNPCKHBW/PUNPCKHWD/PUNPCKHDQ/PUNPCKHQDQ— 解压高数据
PUNPCKLBW/PUNPCKLWD/PUNPCKLDQ/PUNPCKLQDQ—解压低数据
PUSH—将字,双字或四字推到堆栈上
PUSHA/PUSHAD—推送所有通用寄存器
PUSHF/PUSHFD—将EFLAGS寄存器推送到堆栈
PXOR—逻辑异或
RCL/RCR/ROL/ROR—旋转
RCPPS—计算包装的单精度浮点值的倒数
RCPSS—计算标量单精度浮点值的倒数
RDFSBASE/RDGSBASE—读取FS / GS段基址
RDMSR—从模型专用寄存器读取
RDPID—读取处理器ID
RDPKRU—读取用户页面的保护关键权限
RDPMC—读取性能监视计数器
RDRAND—读随机数
RDSEED—阅读随机SEED
RDTSC—读取时间戳计数器
RDTSCP—读取时间戳计数器和处理器ID
REP/REPE/REPZ/REPNE/REPNZ—重复字符串操作前缀
RET—从程序返回
RORX — 向右旋转逻辑而不影响标志
ROUNDPD — 圆形双精度浮点值
ROUNDPS — 圆形封装单精度浮点值
ROUNDSD — 圆形标量双精度浮点值
ROUNDSS — 圆形标量单精度浮点值
RSM—从系统管理模式恢复
RSQRTPS—计算压缩单精度浮点值的平方根的倒数
RSQRTSS—计算标量单精度浮点值的平方根的倒数
SAHF—将AH存储到标志
SAL/SAR/SHL/SHR—转移
SARX/SHLX/SHRX — 转移不影响标志
SBB—借用整数减法
SCAS/SCASB/SCASW/SCASD—扫描字符串
SETcc—在字段上设置字节
SFENCE—商店栅栏
SGDT—存储全局描述符表寄存器
SHA1RNDS4—执行四轮SHA1操作
SHA1NEXTE—计算四轮后的SHA1状态变量E.
SHA1MSG1—对下四个SHA1消息双字执行中间计算
SHA1MSG2—对下四个SHA1消息双字执行最终计算
SHA256RNDS2—执行两轮SHA256操作
SHA256MSG1—对下四个SHA256消息双字执行中间计算
SHA256MSG2—对下四个SHA256消息双字执行最终计算
SHLD—双精度位移左
SHRD—双精度平移
SHUFPD—包装交错双精度浮点值对的随机
SHUFPS—Packed Interleave单精度浮点值四重串交替
SIDT—存储中断描述符表寄存器
SLDT—存储本地描述符表寄存器
SMSW—存储机器状态字
SQRTPD—双精度浮点值的平方根
SQRTPS—单精度浮点值的平方根
SQRTSD—计算平方根的标量双精度浮点值
SQRTSS—计算标量单精度值的平方根
STAC—在EFLAGS寄存器中设置AC标志
STC—设置进位标志
STD—设置方向标志
STI—设置中断标志
STMXCSR—存储MXCSR寄存器状态
STOS/STOSB/STOSW/STOSD/STOSQ—存储字符串
STR—存储任务寄存器
SUB—减去
SUBPD—减去打包的双精度浮点值
SUBPS—减去打包的单精度浮点值
SUBSD—减去标量双精度浮点值
SUBSS—减去标量单精度浮点值
SWAPGS—交换GS基址寄存器
SYSCALL—快速系统调用
SYSENTER—快速系统调用
SYSEXIT—从快速系统调用快速返回
SYSRET—从快速系统调用返回
TEST—逻辑比较
TZCNT — 计算零位的位数
UCOMISD—无序比较标量双精度浮点值并设置EFLAGS
UCOMISS—无序比较标量单精度浮点值并设置EFLAGS
UD2—未定义指令
UNPCKHPD—解包和交织高压双精度浮点值
UNPCKHPS—解包和交织高度封装的单精度浮点值
UNPCKLPD—解包和交织低压双精度浮点值
UNPCKLPS—解包和交织低压缩单精度浮点值

VALIGND/VALIGNQ—对齐双字/四字向量
VBLENDMPD/VBLENDMPS—使用OpMask控件的Blend Float64 / Float32向量
VBROADCAST—加载广播浮点数据
VPBROADCASTM—广播掩码到向量寄存器
VCOMPRESSPD—将稀疏压缩双精度浮点值存储到密集存储器中
VCOMPRESSPS—将稀疏打包的单精度浮点值存储到密集存储器中
VCVTPD2QQ—将打包的双精度浮点值转换为打包的四字整数
VCVTPD2UDQ—将打包的双精度浮点值转换为打包的无符号双字整数
VCVTPD2UQQ—将打包的双精度浮点值转换为打包的无符号四字整数
VCVTPH2PS—将16位FP值转换为单精度FP值
VCVTPS2PH—将Single-Precision FP值转换为16位FP值
VCVTPS2UDQ—将打包的单精度浮点值转换为打包的无符号双字整数值
VCVTPS2QQ—将打包的单精度浮点值转换为打包的有符号四字整数值
VCVTPS2UQQ—将打包的单精度浮点值转换为打包的无符号四字整数值
VCVTQQ2PD—将打包的四字整数转换为打包的双精度浮点值
VCVTQQ2PS—将打包的四字整数转换为打包的单精度浮点值
VCVTSD2USI—将标量双精度浮点值转换为无符号双字整数
VCVTSS2USI—将标量单精度浮点值转换为无符号双字整数
VCVTTPD2QQ—将截断打包的双精度浮点值转换为打包的四字整数
VCVTTPD2UDQ—转换为截断打包的双精度浮点值到打包的无符号双字整数
VCVTTPD2UQQ—将截断的双精度浮点值转换为打包的无符号四字整数
VCVTTPS2UDQ—将截断转换为打包的单精度浮点值到打包的无符号双字整数值
VCVTTPS2QQ—将截断转换为打包的单精度浮点值到打包的有符号四字整数值
VCVTTPS2UQQ—将截断转换为打包的单精度浮点值到打包的无符号四字整数值
VCVTTSD2USI—将截断的标量双精度浮点值转换为无符号整数
VCVTTSS2USI—将截断标量单精度浮点值转换为无符号整数
VCVTUDQ2PD—将打包的无符号双字整数转换为打包的双精度浮点值
VCVTUDQ2PS—将打包的无符号双字整数转换为打包的单精度浮点值
VCVTUQQ2PD—将打包的无符号四字整数转换为打包的双精度浮点值
VCVTUQQ2PS—将打包的无符号四字整数转换为打包的单精度浮点值
VCVTUSI2SD—将无符号整数转换为标量双精度浮点值
VCVTUSI2SS—将无符号整数转换为标量单精度浮点值
VDBPSADBW—对无符号字节的双块打包和绝对差(SAD)
VEXPANDPD—从密集存储器加载稀疏压缩双精度浮点值
VEXPANDPS—从密集存储器加载稀疏打包的单精度浮点值
VERR/VERW—验证读取或写入的段
VEXP2PD—近似于指数2 ^ x的打包双精度浮点值,小于2 ^ -23相对误差
VEXP2PS—近似于包装的单精度浮点值的指数2 ^ x小于2 ^ -23相对误差
VEXTRACTF128/VEXTRACTF32x4/VEXTRACTF64x2/VEXTRACTF32x8/VEXTRACTF64x4—Extr act打包浮点值
VEXTRACTI128/VEXTRACTI32x4/VEXTRACTI64x2/VEXTRACTI32x8/VEXTRACTI64x4—提取打包的整数值
VFIXUPIMMPD—修复特殊打包的Float64值
VFIXUPIMMPS—修复特殊打包的Float32值
VFIXUPIMMSD—修复特殊标量Float64价值
VFIXUPIMMSS—修复特殊标量Float32价值
VFMADD132PD/VFMADD213PD/VFMADD231PD—熔丝乘法 - 加上双精度浮点值
VFMADD132PS/VFMADD213PS/VFMADD231PS—融合乘法 - 加上单精度浮点值
VFMADD132SD/VFMADD213SD/VFMADD231SD—熔丝乘加 - 标量双精度浮点值
VFMADD132SS/VFMADD213SS/VFMADD231SS—融合乘法 - 加上标量单精度浮点值
VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD—熔断乘法 - 交替加/减包装的双精度浮点值
VFMADDSUB132PS/VFMADDSUB213PS/VFMADDSUB231PS—封装单精度浮点值的融合乘法交替加法/减法
VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD—融合乘法交替减法/增加的双精度浮点值
VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS—融合乘法交替减法/添加的单精度浮点值
VFMSUB132PD/VFMSUB213PD/VFMSUB231PD—压缩双精度浮点值的乘法减法
VFMSUB132PS/VFMSUB213PS/VFMSUB231PS—压缩单精度浮点值的乘法减法
VFMSUB132SD/VFMSUB213SD/VFMSUB231SD—标量双精度浮点值的融合乘法 - 减法
VFMSUB132SS/VFMSUB213SS/VFMSUB231SS—标量单精度浮点值的融合乘减
VFNMADD132PD/VFNMADD213PD/VFNMADD231PD—熔丝负精度浮点值的乘积 - 加法
VFNMADD132PS/VFNMADD213PS/VFNMADD231PS—熔丝负精度浮点值的乘积 - 加法
VFNMADD132SD/VFNMADD213SD/VFNMADD231SD—熔丝负精度浮点值的乘积 - 加法
VFNMADD132SS/VFNMADD213SS/VFNMADD231SS—熔丝负精度浮点值的乘积 - 加法
VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD—压缩双精度浮点值的负值乘法减法
VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS—封装单精度浮点值的熔丝负负乘法 - 减法
VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD—标量双精度浮点值的熔融负乘法 - 减法
VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS—标量单精度浮点值的熔点负乘减
VFPCLASSPD—测试打包的Float64值的类型
VFPCLASSPS—测试打包的Float32值的类型
VFPCLASSSD—测试标量Float64值的类型
VFPCLASSSS—测试Scalar Float32值的类型
VGATHERDPD/VGATHERQPD — 使用有符号的双字/ Qword指数收集打包的DP FP值
VGATHERDPS/VGATHERQPS — 使用签名的双字/ Qword索引收集打包的SP FP值
VGATHERDPS/VGATHERDPD—收集包装单,包装双与签署双剑
VGATHERPF0DPS/VGATHERPF0QPS/VGATHERPF0DPD/VGATHERPF0QPD—稀疏预取打包SP / DP数据值与签名双字,签名的Qword指数使用T0提示
VGATHERPF1DPS/VGATHERPF1QPS/VGATHERPF1DPD/VGATHERPF1QPD—稀疏预取打包SP / DP数据值与签名双字,签名的Qword指数使用T1提示
VGATHERQPS/VGATHERQPD—收集包装单,包装双与签名的Qword指数
VPGATHERDD/VPGATHERQD — 使用签名的双字/ Qword指数收集打包的双字值
VPGATHERDD/VPGATHERDQ—收集包装双剑,包装的Qword和双重指数
VPGATHERDQ/VPGATHERQQ — 使用签名的双字/ Qword指数收集打包的Qword值
VPGATHERQD/VPGATHERQQ—收集包装双剑,包装的Qword与已签名的Qword指数
VGETEXPPD—将打包的DP FP值的指数转换为DP FP值
VGETEXPPS—将打包的SP FP值的指数转换为SP FP值
VGETEXPSD—将标量DP FP值的指数转换为DP FP值
VGETEXPSS—将标量SP FP值的指数转换为SP FP值
VGETMANTPD—从Float64 Vector中提取Float64 Vector of Normalized Mantissas
VGETMANTPS—从Float32 Vector中提取Float32向量的Normalized Mantissas
VGETMANTSD—从Float64标量提取Float64的规范化尾数
VGETMANTSS—从Float32向量提取标准化尾数Float32矢量
VINSERTF128/VINSERTF32x4/VINSERTF64x2/VINSERTF32x8/VINSERTF64x4—插入打包的浮点值
VINSERTI128/VINSERTI32x4/VINSERTI64x2/VINSERTI32x8/VINSERTI64x4—插入打包的整数值
VMASKMOV—条件SIMD打包荷载和商店
VPBLENDD — 混合包装双字
VPBLENDMB/VPBLENDMW—使用opmask控制的混合字节/字向量
VPBLENDMD/VPBLENDMQ—使用OpMask控件混合Int32 / Int64向量
VPBROADCASTB/W/D/Q—从通用寄存器加载广播整数数据
VPBROADCAST—加载整数和广播
VPCMPB/VPCMPUB—将打包的字节值比较到掩码中
VPCMPD/VPCMPUD—将打包的整数值与掩码进行比较
VPCMPQ/VPCMPUQ—将打包的整数值与掩码进行比较
VPCMPW/VPCMPUW—比较打包的词值到掩码
VPCOMPRESSD—将稀疏压缩双字整数值存储到密集存储器/寄存器中
VPCOMPRESSQ—将稀疏压缩四字整数值存储到密集存储器/寄存器中
VPCONFLICTD/Q—检测在打包的双字/ Qword值的向量内的冲突到密集存储器/寄存器中
VPERM2F128 — 允许浮点值
VPERM2I128 — 允许整数值
VPERMD/VPERMW—Permute打包双字/字元素
VPERMI2W/D/Q/PS/PD—两个表的完全权限覆盖索引
VPERMILPD—允许双精度浮点值对的内部通道
VPERMILPS—允许四精度浮点值的内部通道
VPERMPD—允许双精度浮点元素
VPERMPS—允许单精度浮点元素
VPERMQ—四字节元素置换
VPEXPANDD—从密集存储器/寄存器加载稀疏压缩双字整数值
VPEXPANDQ—从密集存储器/寄存器加载稀疏压缩四字整数值
VPLZCNTD/Q—计算打包双字,打包的Qword值的前导零位数
VPMASKMOV — 条件SIMD整数打包荷载和商店
VPMOVM2B/VPMOVM2W/VPMOVM2D/VPMOVM2Q—将屏蔽寄存器转换为向量寄存器
VPMOVB2M/VPMOVW2M/VPMOVD2M/VPMOVQ2M—将矢量寄存器转换为掩码
VPMOVQB/VPMOVSQB/VPMOVUSQB—Down将QWord转换为字节
VPMOVQW/VPMOVSQW/VPMOVUSQW—Down将QWord转换为Word
VPMOVQD/VPMOVSQD/VPMOVUSQD—Down将QWord转换为DWord
VPMOVDB/VPMOVSDB/VPMOVUSDB—Down将DWord转换为字节
VPMOVDW/VPMOVSDW/VPMOVUSDW—Down将DWord转换为Word
VPMOVWB/VPMOVSWB/VPMOVUSWB—向下将字转换为字节
PROLD/PROLVD/PROLQ/PROLVQ—位向左旋转
PRORD/PRORVD/PRORQ/PRORVQ—位向右旋转
VPSCATTERDD/VPSCATTERDQ/VPSCATTERQD/VPSCATTERQQ—分散包装双字,带有符号双字的打包字,签名的Qword指数
VPSLLVW/VPSLLVD/VPSLLVQ—可变位移左逻辑
VPSRAVW/VPSRAVD/VPSRAVQ—可变位移右算术
VPSRLVW/VPSRLVD/VPSRLVQ—可变位移右逻辑
VPTERNLOGD/VPTERNLOGQ—按位三进制逻辑
VPTESTMB/VPTESTMW/VPTESTMD/VPTESTMQ—逻辑与和设置掩码
VPTESTNMB/W/D/Q—逻辑NAND和设置
VRANGEPD—对于Float64值的打包对的范围限制计算
VRANGEPS—对于Float32值的打包对的范围限制计算
VRANGESD—范围限制计算从一对Scalar Float64值
VRANGESS—从一对标量Float32值计算范围限制
VRCP14PD—计算压缩Float64值的近似倒数
VRCP14SD—计算标量Float64值的近似倒数
VRCP14PS—计算压缩Float32值的近似倒数
VRCP14SS—计算标量Float32值的近似倒数
VRCP28PD—近似于具有小于2 ^ -28相对误差的封装双精度浮点值的倒数
VRCP28SD—近似于标量双精度浮点值的倒数,小于2 ^ -28相对误差
VRCP28PS—近似于具有小于2 ^ -28相对误差的封装单精度浮点值的倒数
VRCP28SS—近似于标量单精度浮点值的倒数,小于2 ^ -28相对误差
VREDUCEPD—对压缩的Float64值执行压缩转换
VREDUCESD—对标量Float64值执行减少转换
VREDUCEPS—对已压缩的Float32值执行减少转换
VREDUCESS—对标量Float32值执行减少转换
VRNDSCALEPD—圆形压缩Float64值以包括给定数目的分数位
VRNDSCALESD—圆形标量浮点值包括给定数量的比特位
VRNDSCALEPS—圆形压缩Float32值以包括给定数目的分数位
VRNDSCALESS—圆形标量浮点值包括给定数量的比特位
VRSQRT14PD—计算压缩Float64值的平方根的近似倒数
VRSQRT14SD—计算标量Float64值的平方根的近似倒数
VRSQRT14PS—计算压缩Float32值的平方根的近似倒数
VRSQRT14SS—计算标量Float32值的平方根的近似倒数
VRSQRT28PD—近似于包装的双精度浮点值的倒数平方根,小于2 ^ -28相对误差
VRSQRT28SD—近似于标量双精度浮点值的倒数平方根,小于2 ^ -28相对误差
VRSQRT28PS—近似于包装的单精度浮点值的倒数平方根,小于2 ^ -28相对误差
VRSQRT28SS—近似于标量单精度浮点值的倒数平方根,小于2 ^ -28相对误差
VSCALEFPD—使用Float64值缩放打包的Float64值
VSCALEFSD—使用Float64值缩放Scalar Float64值
VSCALEFPS—使用Float32值缩放打包的Float32值
VSCALEFSS—使用Float32值缩放标量浮点32值
VSCATTERDPS/VSCATTERDPD/VSCATTERQPS/VSCATTERQPD—分散包装单,包装双与签署的双剑和指数
VSCATTERPF0DPS/VSCATTERPF0QPS/VSCATTERPF0DPD/VSCATTERPF0QPD—稀疏预取打包SP / DP数据值与签名双字,签名的Qword指数使用T0提示与意图写
VSCATTERPF1DPS/VSCATTERPF1QPS/VSCATTERPF1DPD/VSCATTERPF1QPD—稀疏预取打包SP / DP数据值与签名双字,签名的Qword指数使用T1提示与意图写
VSHUFF32x4/VSHUFF64x2/VSHUFI32x4/VSHUFI64x2—随机播放128位粒度的打包值
VTESTPD/VTESTPS—压缩位测试
VZEROALL—零所有YMM寄存器
VZEROUPPER—YMM寄存器的零上限位
WAIT/FWAIT—等待
WBINVD—回写并使缓存无效
WRFSBASE/WRGSBASE—写FS / GS段基
WRMSR—写入模型专用寄存器
WRPKRU—将数据写入用户页密钥寄存器
XACQUIRE/XRELEASE — 硬件锁Elision Prefix提示
XABORT — 事务中止
XADD—交换和添加
XBEGIN — 事务开始
XCHG—与寄存器交换寄存器/存储器
XEND — 事务结束
XGETBV—获取扩展控制寄存器的值
XLAT/XLATB—表查找翻译
XOR—逻辑异或
XORPD—压缩双精度浮点值的按位逻辑异或
XORPS—压缩单精度浮点值的按位逻辑异或
XRSTOR—恢复处理器扩展状态
XRSTORS—恢复处理器扩展状态主管
XSAVE—保存处理器扩展状态
XSAVEC—使用压缩保存处理器扩展状态
XSAVEOPT—保存处理器扩展状态优化
XSAVES—保存处理器扩展状态主管
XSETBV—设置扩展控制寄存器
XTEST — 测试如果在事务执行