首页
导航
博客
电子书
算法
众创
代码
随贴
关于我们
您好,欢迎来到码863代码分享网! 请
[登录]
/
[注册]
搜 索
标题:
*
140
字
TAG标签:
(用空格隔开)
30
字
恢复历史版本:
2023-12-29 15:31:59
2023-12-27 13:56:50
2023-12-27 13:43:26
2023-12-26 20:40:29
2023-12-26 17:27:50
2023-12-26 16:48:23
请选择分类
html
python
javascript
php
sql
c
c++
c#
java
plain
所有人可见
仅自己可见
编辑器:UEditor
编辑器:TinyMCE
编辑器:Editor.md
HTML转MD
HTML转MD2
#重要资料导航 [nasm官方文档](https://www.nasm.us/xdoc/2.15.01/html/nasmdocb.html#section-B.1.2 "nasm指令") [bochs调试命令](https://bochs.sourceforge.io/doc/docbook/user/internal-debugger.html "bochs调试命令") [Intel®64和IA-32架构软件开发人员手册](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html "Intel®64和IA-32架构软件开发人员手册") [中断及8259A芯片详解](https://blog.csdn.net/Wang_Dou_Dou_/article/details/122037133 "中断及8259A芯片详解") [Intel手册中的各种符号意义1](https://blog.csdn.net/shadow20080578/article/details/41787493 "Intel手册中的各种符号意义1") [Intel手册中的各种符号意义2](https://blog.csdn.net/m0_50474278/article/details/126376300 "Intel手册中的各种符号意义2") [INT 15H探测内存](https://blog.csdn.net/sourcex/article/details/102591070 "INT 15H探测内存") 学汇编与操作系统好书推荐: x86汇编语言:从实模式到保护模式(第2版) 主要内容讲述16位及32位汇编写内核,内核入门 一个64位操作系统的设计与实现 入门第二本书 30天自制操作系统 主要内容用汇编联合C语言编译(C为主)写操作系统 ##debug | 查看、修改寄存器 | 查看内存 | 修改内存 | 反汇编 | 单步 | 写汇编: | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | | R | D | E | U | T | A | ## Bochs调试器指令 ### 执行控制 * **c**: 继续执行 * **s**: 单步执行 * **b**: 设置断点 * **del**: 删除断点 * **reset**: 重置仿真器 * **quit/q**: 退出调试器 ### 查看信息 * **r**: 显示寄存器状态 * **info cpu**: 显示CPU状态 * **info idt**: 查看中断描述符表 * **info gdt**: 查看全局描述符表 * **info pic**: 查看可编程中断控制器状态 * **info tlb**: 查看转换后援缓冲 * **info cr0/cr2/cr3/cr4**: 显示控制寄存器内容 * **info eflags**: 显示eflags寄存器内容 * **info sreg**: 显示段寄存器 * **info ldt**: 查看局部描述符表 * **info io**: 查看I/O位图 * **info msr**: 查看模型特定寄存器 * **info pci**: 查看PCI设备信息 ### 内存与反汇编 * **x/格式 地址**: 检查内存内容 * **disassemble/u**: 从指定地址开始反汇编 * **d/dl/dt**: 以不同格式显示内存内容 ### 调试功能 * **watch read/write 地址**: 设置读/写监视点 * **lb**: 设置逻辑断点 * **info tab**: 列出逻辑断点 * **trace-on/trace-off**: 开启/关闭指令追踪 ### 符号管理 * **load-syms \[参数\]**: 从文件加载符号 * **info symbols \[参数\]**: 显示加载的符号 * **ldsym**: 加载动态符号 ### 其他命令 * **v2l seg:offset**: 虚拟地址转为线性地址 * **set \[寄存器\] 值**: 设置寄存器的值 * **set\_cpu**: 设置CPU特性 * **info time**: 显示仿真器内部时间 ##bochs难点 lb|lbreak [addr]以线性地址添加断点 pb|pbreakb|break [addr]以物理地址添加断点 以指令数打断点: sb [delta] delta 表示增量number of ticks,执行delta of ticks就中断 sba [time] CPU从运行开始,执行第time条指令时中断,从0开始的指令数 以读写IO打断点: watch r|read [phy_addr]设置读断点 wath w[write [phy_addr]设置写断点 watch 显示所有读写断点 unwatch清除所有断点 unwatch [phy_addr]清除在此地址上的读写断点 bpd|bpe [n]禁用断点(break point disable)/启用断点(break point enable),n是断点号,可以用blist命令先检查出来 d|del[delete [n]删除某断点,n是断点号,可以用blist命令先查出来 watch w 0x7e10 watch w 0x8000 watch w 0x8200 x /20w 0x7e00 #一天写出简单的操作系统引导程序 ##引导代码 ``` mov ax,0xb800 ;显存段地址存入ds,不能直接存,电脑没这个电路 mov ds,ax mov byte [0x00],'a' ;要显示的字符存入显存 mov byte [0x02],'b' ;高位不写默认0x07,背景黑0000前景白0111。 jmp $ ;$为本行偏移地址,死循环 times 510-($-$$) db 0 ;用0补足512字节,$$为起始偏移地址 因为一共为512字节,512-2-(当前偏移-0) db 0x55,0xaa ;如果其是有效的引导扇区,最后2字节应当是0x55和0xAA ``` 把这段代码通过编译后,再通过二进制编辑软件写入一个空的固定尺寸引导扇区,即时执行 nasm -f bin 1.asm -l 1.lst   ##寄存器    | 64-bit | 32-bit | 16-bit | 8-bit (low) | | --- | --- | --- | --- | | RAX | EAX | AX | AL | | RBX | EBX | BX | BL | | RCX | ECX | CX | CL | | RDX | EDX | DX | DL | | RSI | ESI | SI | SIL | | RDI | EDI | DI | DIL | | RBP | EBP | BP | BPL | | RSP | ESP | SP | SPL | | R8 | R8D | R8W | R8B | | R9 | R9D | R9W | R9B | | R10 | R10D | R10W | R10B | | R11 | R11D | R11W | R11B | | R12 | R12D | R12W | R12B | | R13 | R13D | R13W | R13B | | R14 | R14D | R14W | R14B | | R15 | R15D | R15W | R15B | 16位的寄存器中,可以访问高8位的数据 | 16-bit | 8-bit (high) | | --- | --- | | AX | AH | | BX | BH | | CX | CH | | DX | DH | 32位寄存器 - eax:通常用来执行加法,函数调用的返回值一般也放在这里面 - ebx:数据存取 - ecx:通常用作计数器,比如for循环 - edx:暂不清楚 - esp:栈顶指针,指向栈的顶部 - ebp:栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量 - edi:字符串操作时,用于存放数据源的地址 - esi:字符串操作时,用于存放目的地址的,和edi两个经常搭配一起使用,执行字符串的复制等操作 64位的寄存器 - r- ax:通常用于存储函数调用返回值 - rsp:栈顶指针,指向栈的顶部 - rdi:第一个入参 - rsi:第二个入参 - rdx:第三个入参 - rcx:第四个入参 - r8:第五个入参 - r9:第六个入参 - rbx:数据存储,遵循Callee Save原则 - rbp:数据存储,遵循Callee Save原则 - r12~r15:数据存储,遵循Callee Save原则 - r10~r11:数据存储,遵循Caller Save原则 这8个16位寄存器,可以互相传送数据,也可以进行算术逻辑运算;也可以在和内存单元之间进行16位的数据传送或者算术逻辑运算,可分为8位的8个也同样。 cs,ds,es,ss为段寄存器,ip为指令寄存器,cs与ip结合指向正运行的指令内存位置 除了段寄存器与ip,其它都可以给立即数。 ##8086内存分布  ##80×25文本模式 电脑开机自检后载入硬盘引导前默认进入此文本模式 从B800:0000开始写入ASCII码即可显示英文 屏幕上每个字符对应着显存中连续2字节,前一个是ASCII代码,后面是字符的显示属性,包括字符颜色和底色(前景与背景),默认为0x07前景黑背景白。   ##寻址 - 8086有20位地址线,2^20=1M,寻址范围1,048,576字节 - 因为8086实模式下寄存器为16位,可以这么理解,用段寄存器存前16位,再加一个后4位数即可形寻址20位。 - 理解为 ffff0+f=fffff=ffff*10+f=65535*16+65535=1,048,575(0-1,048,575共寻址1,048,576) - 电脑内部是这么做的,段寄存器存前16位,再可以加上一个16位二进制数形成逻辑地址,与上面4位有区别,因为只要两数相加不超过1M,都可以得出一个正确的物理地址 - 即:物理地址00010,可以表述为逻辑地址0001:0000 , 0001为段地址,0000为偏移地址 - 物理地址fffff,可表述为ffff:000f 也可表述这f000:ffff 或ff00:0fff等等但相加不能超过fffff  - cs,ds,es,ss为段寄存器,cs为指令段寄存器,ds数据段,es扩展段,ss栈段 - cs:ip指向当前运行的内存地址,ds:偏移量为当前数据地址 - nasm中用jmp指令更改cs与ip,如 jmp 0x3000:0000; ##硬盘结构   硬盘可以只有一个盘片(单碟),也可能有好几个盘片,转速有的能达到一万多转 每个盘片都有两个磁头(Head),上下各一个,经常用磁头来指盘面。磁头都有编号,上面的磁头编号为0,下面的磁头编号为1;第2个盘片依次类推。 磁头(Head)读写数据时绕着圆心“画”出一个看不见的圆圈,这就是磁道,最外圈为0磁道,一圈磁道可分为N个扇区(sector)一般为63个,一个扇区512字节,扇区从编号1开始。硬盘读写以扇区为最小单位的,所以每次读写最少为512字节。 扇区之间以空白间隔开来,每个扇区以扇区头开始,然后是512字节的数据区。扇区头包含扇区的信息,主要有本扇区的磁道号、磁头号和扇区号。现代硬盘还包含指示扇区健康的标志,以及用来替换坏扇区的扇区地址 硬盘通过移动磁头来读取磁性数据,每个磁头不是单独移动的,它们固定在同一个支架上同进退,由步进电动机带动着在盘片中心和边缘来回移动读数据。步进电动机由脉冲驱动,每次旋转一固定角度,即步进一次。 读写数据从0磁头即0磁道0面1扇区(即chs)开始,移动磁头是一个机械动作,看似很快但对处理器来说却很漫长,这就是寻道时间。为了加快读写,尽量不移动磁头。当读写完0面0磁道所有扇区时,应当读写在1面(1碰头)的同一磁道上。以此类推,依次读写2,3,4...面同磁道数据,直到读写完这个柱面(Cylinder),再读写第二个柱面,以此类推。 0柱0头1扇区为引导扇区 ##逻辑扇区 采用磁道、磁头、扇区这种模式称为CHS模式,但不方便。如果有一大堆数据要写,还得注意磁头号、磁道号和扇区号不要超过界限。所以后来引入了逻辑块地址(LogicalBlock Address, LBA)的概念。现在市场上销售的硬盘,无论哪个厂家生产的,都支持LBA模式。LBA模式由硬盘控制器在硬件一级上提供支持,所以效率很高,兼容性很好。逻辑地址即为按以上分析的顺序给物理扇区编号。 逻辑0扇区从0柱0头1扇区开始->0柱0头N扇->0柱1头1扇->0柱1头N扇,读完0柱所有头所有扇区,,再从1柱面开始读写1柱0头1扇,类推 ##加电过程 intel系的cpu加电后,自动初始化所有寄存器为0,除了cs为ffff,ip为0,然后跳到ffff:0,这位于bios地址内,进行自检初始化各种硬件设备,完成后会加硬盘引导扇区加载到0000:7c00,即物理地址07c00。 硬盘的第一个扇区是0柱面0磁头1扇区(0面0道1扇),即为主引导扇区。如果计算机的设置是从硬盘启动的,那么ROM-BIOS将读取硬盘主引导扇区512字节的内容,**如果是有效的引导扇区,最后2字节应当是0x55和0xAA**,那么将它加载到内存地址 0x0000:0x7c00(也就是物理地址0x07C00),然后用一个jmp指令跳到那里接着执行操作系统启动。 ##虚拟机虚拟硬盘 VHD(Virtual Hard Disk)为VirtualBox支持的一种虚拟硬盘结构。新建时选固定尺寸 在VHD规范里,每个扇区是512字节。VHD文件一开始的512字节就对应着物理硬盘的0柱0头1引导扇区。然后,VHD文件的第二个512字节,对应着0柱0头2扇区,依次类推直到0柱0头n扇区。后面数据都按此排列,对应着逻辑扇区。 在VHD文件的结尾,包含了512字节的格式信息以一个字符串“conectix”开始的,包含了诸如文件的创建日期、VHD的版本、创建该文件的应用程序名称和版本、创建该文件的应用程序所属的操作系统、该虚拟硬盘的参数(磁头数、每面磁道数、每磁道扇区数)、VHD类型(固定尺寸还是动态增长)、虚拟硬盘容量等 VHD逻辑扇区0即为引导扇区,所以写入一段代码到此即可由电脑执行。  #知识点 ##常见十六进制与十进制对照表 |十进制|十六进制|可读| | ----: | ----: | ----: | |256|100|100| |512|200|200| |1024|400|1kb| |2048|800|2kb| |4096|1000|4kb| |8192|2000|8kb| |16384|4000|16kb| |32768|8000|32kb| |65536|10000|64kb| |131072|20000|128kb| |262144|40000|256kb| |524288|80000|512kb| |1048576|100000|1Mb| |2097152|200000|2Mb| |4194304|400000|4Mb| |8388608|800000|8Mb| |16777216|1000000|16Mb| |33554432|2000000|32Mb| ##FAT12 > FAT16、FAT32等FAT类文件系统都是在FAT12文件系统的基础上扩展而得 ###FAT12结构  [FAT12结构图2](/ueditor/tinymce/20231221/kSFK4kBd.png "FAT12结构图") ###FAT12存储结构  [FAT12存储结构图2](/ueditor/tinymce/20231221/RQKWwuhe.png "FAT12存储结构图2") ###FAT表项每项12B > FAT表中的表项与数据区的簇是一一对应的关系,即一个表项对应一个簇。 | FAT 项 | 可取值 | 描述 | | --- | --- | --- | | 0 | BPB\_Media | 磁盘标识字,低字节需与 BPB\_Media 数值保持一致 | | 1 | FFFh | 表示第一个簇已占用 | | 2 ~ N | 000h | 可用簇 | || 002h~FEFh | 已用簇 | || FF0h~FF6h | 保留簇 | || FF7h | 坏簇 | || FF8h~FFFh | 文件的最后一个簇 | ###FAT12引导扇区 [FAT12引导扇区图表说明](/ueditor/tinymce/20231221/cNTUSMbJ.png "FAT12图表说明") | 名称 | 偏移 | 长度 | 内容 | 软盘参考值 | | --- | --- | --- | --- | --- | | BS\_jmpBoot | 0 | 3 | \- | jmp LABEL\_START nop | | BS\_OEMName | 3 | 8 | 厂商名 | 'ForrestY' | | BPB\_BytsPerSec | 11 | 2 | 每扇区字节数 | 0x200(即十进制512) | | BPB\_SecPerClus | 13 | 1 | 每 [簇](/item/簇/13014767?fromModule=lemma_inlink) 扇区数 | 0x01 | | BPB\_RsvdSecCnt | 14 | 2 | Boot记录占用多少扇区 | 0x01 | | BPB\_NumFATs | 16 | 1 | 共有多少FAT表 | 0x02 | | BPB\_RootEntCnt | 17 | 2 | [根目录](/item/根目录/6061330?fromModule=lemma_inlink) 文件数最大值 | 0xE0 (224) | | BPB\_TotSec16 | 19 | 2 | 扇区总数 | 0xB40(2880) | | BPB\_Media | 21 | 1 | 介质描述符 | 0xF0 | | BPB\_FATSz16 | 22 | 2 | 每FAT扇区数 | 0x09 | | BPB\_SecPerTrk | 24 | 2 | 每磁道扇区数 | 0x12 | | BPB\_NumHeads | 26 | 2 | 磁头数 | 0x02 | | BPB\_HiddSec | 28 | 4 | 隐藏扇区数 | 0 | | BPB\_TotSec32 | 32 | 4 | 如果BPB\_TotSec16是0,由这个值记录扇区数 | 0xB40(2880) | | BS\_DrvNum | 36 | 1 | 中断13的驱动器号 | 0 | | BS\_Reserved1 | 37 | 1 | 未使用 | 0 | | BS\_BootSig | 38 | 1 | 扩展引导标记 | 0x29 | | BS\_VolD | 39 | 4 | 卷序列号 | 0 | | BS\_VolLab | 43 | 11 | 卷标 | 'OrangeS0.02' | | BS\_FileSysType | 54 | 8 | 文件系统类型 | 'FAT12' | | 引导代码 | 62 | 448 | 引导代码、数据及其他填充字符等 | \- | | 结束标志 | 510 | 2 | \- | 0xAA55 | ###文件目录项有32个字节 | 名称 | 偏移 | 长度 | 描述 | | --- | --- | --- | --- | | DIR\_Name | 0 | 0xB | 文件名8字节,扩展名3字节 | | DIR\_Attr | 0xB | 1 | 文件属性 | | 保留 | 0xC | 10 | \- | | DIR\_WrtTime | 0x16 | 2 | 最后修改时间 | | DIR\_WrtDate | 0x18 | 2 | 最后修改日期 | | DIR\_FstClus | 0x1A | 2 | 此条目对应的开始簇号 | | DIR\_FileSize | 0x1C | 4 | 文件大小 | ###FAT12引导扇区详解 - BS_OEMName。记录制造商的名字,亦可自行为文件系统命名。 - BPB_SecPerClus。描述了每簇扇区数。由于每个扇区的容量只有512 B,过小的扇区容量可能会导致软盘读写次数过于频繁,从而引入簇(Cluster)这个概念。簇将2的整数次方个扇区作为一个“原子”数据存储单元,也就是说簇是FAT类文件系统的最小数据存储单位。 - BPB_RsvdSecCnt。指定保留扇区的数量,此域值不能为0。保留扇区起始于FAT12文件系统的第一个扇区,对于FAT12而言此位必须为1,也就意味着引导扇区包含在保留扇区内,所以FAT表从软盘的第二个扇区开始。 - BPB_NumFATs。指定FAT12文件系统中FAT表的份数,任何FAT类文件系统都建议此域设置为2。设置为2主要是为了给FAT表准备一个备份表,因此FAT表1与FAT表2内的数据是一样的,FAT表2是FAT表1的数据备份表。 - BPB_RootEntCnt。指定根目录可容纳的目录项数。对于FAT12文件系统而言,这个数值乘以32必须是BPB_BytesPerSec的偶数倍。 - BPB_TotSec16。记录着总扇区数。这里的总扇区数包括保留扇区(内含引导扇区)、FAT表、根目录区以及数据区占用的全部扇区数,如果此域值为0,那么BPB_TotSec32字段必须是非0值。 - BPB_Media。描述存储介质类型。对于不可移动的存储介质而言,标准值是0xF8。对于可移动的存储介质,常用值为0xF0,此域的合法值是0xF0、0xF8、0xF9、0xFA、0xFB、0xFC、0xFD、0xFE、0xFF。另外提醒一点,无论该字段写入了什么数值,同时也必须向FAT[0]的低字节写入相同值。 - BPB_FATSz16。记录着FAT表占用的扇区数。FAT表1和FAT表2拥有相同的容量,它们的容量均由此值记录。 - BS_VolLab。指定卷标。它就是Windows或Linux系统中显示的磁盘名。 - BS_FileSysType。描述文件系统类型。此处的文件系统类型值为’FAT12',这个类型值只是一个字符串而已,操作系统并不使用该字段来鉴别FAT类文件系统的类型。 ###汇编引导扇区MBR ``` ; 以下的记述用于标准FAT12格式的软盘 JMP entry ; 跳转到entry处执行 注意:该跳转指令只占用2个字节,而标准规定的是3个字节 所以才会有下面的DB 0x90 DB 0x90 ; 机器码,事实上,这相当于一个"nop"指令,即空指令 DB "HELLOIPL" ; 启动区的名称 DW 512 ; 每扇区字节数 DB 1 ; 每簇的扇区数 此处为1 表面一个簇就等于一个扇区 DW 1 ; 这个值应该表示为第一个FAT文件分配表之前的引导扇区,一般情况只保留一个扇区 DB 2 ; FAT表的个数 DW 224 ; 根目录中文件数的最大值 DW 2880 ; 逻辑扇区总数 DB 0xf0 ; 磁盘的种类 DW 9 ; 每个FAT占用多少个扇区 DW 18 ; 每磁道扇区数 DW 2 ; 磁头数 DD 0 ; 隐藏扇区数 DD 2880 ; 如果逻辑扇区总数为0,则在这里记录扇区总数 DB 0,0,0x29 ; 中断13的驱动器号、未使用、扩展引导标志 DD 0xffffffff ; 卷序列号 DB "HELLO-OS " ; 卷标,必须是11个字符,不足以空格填充 DB "FAT12 " ; 文件系统类型,必须是8个字符,不足填充空格 RESB 18 ; 先空出18字节 ``` ##负数 - 负数为0-n,8位0-1=0xff,指令neg al,把al变成负数,如al=1,neg al后值为0xff - cbw(Convert Byte to Word)AL有符号数扩展AX,如-1,AL=0xff,cbw,ax=0xffff - cwd(Convert Word to Double-word)AX有符号数扩展DX:AX,如-1,AX=0xffff,cwd,DX:AX=0xffffffff ##标号 标号可以由字母 数字 _ $ # @ ~ . ?组成,但必须以字母 ._和?中的任意一个打头。 ##栈 后进先出,每次2字节,任意时刻ss:sp指向栈顶,push入栈先sp-2,再存入腾出的位置,pop相反先出再加。   push对象立即数,寄存器(除了状态寄存器),内存单元,pop相似 ##寻址方式 16位下BX,BP为基址,SI,DI为变址,只有四个参与寻址  32位下除ESP不能作变址 可以使用全部的32位通用寄存器作为基址寄存器。同时,还可以再加上一个除ESP外的32位通用寄存器作为变址寄存器。变址寄存器还允许乘以1、2、4或者8作为比例因子。最后,还允许加上一个8位或者32位的位移。   ##转移指令 - 修改IP或同时修改CS的指令,nasm除了far不能省略,short与near都可省略 - 段内转移只改IP jmp ax , jmp [0001] ,jmp [bx] 对应(jmp ax , jmp word ptr ds:0x01 ,jmp word ptr ds:[bx]) - 段间转移改CS:IP jmp 1000:0 - 短转移与近转移 - 短转移ip修改范围-128~127(8位) jmp 标号 - 近转移ip修改范围-32768~32767(16位) jmp near 标号   ##MSR寄存器 MSR(Model Specific Register)是x86架构中的概念,指的是在x86架构处理器中,一系列用于控制CPU运行、功能开关、调试、跟踪程序执行、监测CPU性能等方面的寄存器。 到Intel Pentium处理器的时候,Intel正式引入RDMSR和WRMSR两个指令用于读和写MSR寄存器,这个时候MSR就算被正式引入。在引入RDMSR和WRMSR指令的同时,也引入了CPUID指令,该指令用于指明具体的CPU芯片中,哪些功能是可用的,或者这些功能对应的MSR寄存器是否存在,软件可以通过CPUID指令查询某些功能是否在当前CPU上是否支持。 每个MSR寄存器都会有一个相应的ID,即MSR Index,或者也叫作MSR寄存器地址,当执行RDMSR或者WRMSR指令的时候,只要提供MSR Index就能让CPU知道目标MSR寄存器。这些MSR寄存器的编号(MSR Index)、名字及其各个数据区域的定义可以在Intel x86架构手册”Intel 64 and IA-32 Architectures Software Developer’s Manual”的Volume 4中找到。 ##控制寄存器  ###CR4 用于控制CPU的特性和操作系统的行为。它的作用如下: 控制分页机制:x86CR4寄存器的最重要作用是控制分页机制。在64位x86处理器中,x86CR4寄存器的第5位(PAE)控制是否启用物理地址扩展(Physical Address Extension,PAE)模式,第7位(PSE)控制是否启用页大小扩展(Page Size Extension,PSE)模式,第12位(PCIDE)控制是否启用页表缓存(Page Directory Cache,PDC)。 启用SMEP和SMAP保护机制:x86CR4寄存器的第20和第21位控制启用Supervisor Mode Execution Protection(SMEP)和Supervisor Mode Access Prevention(SMAP)保护机制。 启用虚拟化扩展:x86CR4寄存器的第13位控制是否启用虚拟化扩展(Virtualization Extension,VME)。 其他:x86CR4寄存器还控制着其他一些特性,如Debugging Extensions(DE)、Machine Check Exception(MCE)和Page Attribute Table(PAT)等。 在Linux内核中,x86CR4寄存器的主要作用是控制分页机制和启用SMEP和SMAP保护机制。 ###CR3 - PWT(Page-level Write-Through)是页级通写位,和高速缓存有关。“通写”是处理器高速缓存的一种工作方式,这一位用来间接决定是否采用此种方式来改善页面的访问效率。 - PCD(Page-level Cache Disable)是页级高速缓存禁止位,用来间接决定该表项所指向的那个页是否使用高速缓存策略。 cr3寄存器和MMU密切相关,保存了当前进程所使用的虚拟地址空间的页目录地址,可以说是整个虚拟地址翻译中的顶级指挥棒,在进程空间切换的时候,CR3也将同步切换。 cr3寄存器的高20位用于保存页目录地址,0-11位记录标记位,所以页目录地址必须是4KB的整数 ###CR2 页故障线性地址寄存器,也称为页故障地址寄存器(Page Fault Linear Address Register)。当CPU检测到一个页故障(Page Fault),将故障发生时的线性地址存储在其中,这个地址指向导致页故障的页面。 内核可以通过读取CR2寄存器来获取引起页故障的地址,然后对该地址所在的页面进行处理,比如进行页面的分配或者进行页面的交换。CR2寄存器的值可以在中断或异常处理例程中读取。 在保护模式下,访问CR2寄存器需要使用特殊的指令,比如MOV CR2, EAX将EAX寄存器的值写入CR2寄存器,或MOV EAX, CR2将CR2寄存器的值读取到EAX寄存器中。在x86_64架构下,CR2寄存器的大小为64位。 ###CR0 - PG:开启分页模式 - CD:控制Cache高速缓存功能,CD=1关闭该功能 - NW:控制使用通写还是回写,用于维护内存数据一致性,NW=1关闭该功能,数据一致性即通过MESI协议 - AM:控制启用内存对齐自动检查 - WP:控制开启内存写保护,WP=0开启写保护,对只读页面尝试写入将触发异常,这一机制常常被用来实现写时复制功能 - PE:如果PE=1,则保护模式启动,如果PE=0,则在实模式下运行 ##调试寄存器 帮助和加速软件调试器的寄存器(Debug registers),如GDB。 有6个调试寄存器,分为两种类型:DR0到DR3包含线性地址,每个地址都与一个断点条件相关。 DR6和DR7是调试状态和控制寄存器。DR6的低位表示遇到了哪些调试条件(在进入调试异常处理程序时),而DR7控制哪些断点地址被启用以及它们的断点条件(例如,当某一地址被写入时)。 ##标志寄存器 RFLAGS高32位保留与EFLAGS一致,16位为FLAGS  - CF(Carry Flag):进位标志。当执行加法或减法运算时,如果结果产生进位,则CF被设置为1。在二进制加法中,如果最高位(符号位)产生进位,则CF被设置为1。 - PF(Parity Flag):奇偶标志。当数据字节中的1的个数为偶数时,PF被设置为1;为奇数时,PF被设置为0。 - AF(Auxiliary Carry Flag):辅助进位标志。在执行某些算术运算时,如果低4位向高4位有进位或借位,则AF被设置为1。 - ZF(Zero Flag):零标志。当操作结果为0时,ZF被设置为1;否则,ZF被设置为0。 - SF(Sign Flag):符号标志。当操作结果为负数时,SF被设置为1;为正数或零时,SF被设置为0。 - TF(Trap Flag):陷阱标志。TF用于控制异常处理。当TF设置为1时,CPU在每个指令的结束处产生一个中断,以便执行异常处理程序。 - IF(Interrupt Flag):中断标志。IF用于控制中断的启用和禁用。当IF设置为1时,CPU允许外部中断INTR;为0时,禁止外部中断。 - DF(Direction Flag):方向标志。DF用于控制串操作的方向。当DF设置为1时,从高地址到低地址移动数据;为0时,从低地址到高地址移动数据。 - OF(Overflow Flag):溢出标志。当执行有符号整数运算时,如果结果溢出,则OF被设置为1。 不同处理器行为不同  M:依计算结果而定 0:固定为0 |指令|对标志位的影响| | ------------ | ------------ | |add | OF、SF、ZF、AF、CF 和 PF 的状态依计算结果而定。| |and | OF=0,CF=0;对 SF、ZF 和 PF 的影响依计算结果而定。| |cbw | 不影响任何标志位。| |cld | DF=0,CF、OF、ZF、SF、AF 和 PF 未定义。未定义的意思是到目前为止还不打算让该指令影响到这些标志,因此,不要在程序中依赖这些标志。| |cwd | 不影响任何标志位。| |dec | CF 标志不受影响,因为该指令通常在程序中用于循环计数,而且在循环体内通常有依赖 CF 标志的指令,故不希望它打扰 CF 标志;对 OF、SF、ZF、AF 和PF 的影响依计算结果而定。| |div/idiv | 对 CF、OF、SF、ZF、AF 和 PF 的影响未定义。| |inc | CF 标志不受影响,对 OF、SF、ZF、AF 和 PF 的影响依计算结果而定。| |mov/movs | 这类指令不影响任何标志位。| |neg | 如果操作数为 0,则 CF=0,否则 CF=1;对 OF、SF、ZF、AF 和 PF 的影响依计算结果而定。| |std | DF=1,不影响其他标志位。| |sub | 对 OF、SF、ZF、AF、PF 和 CF 的影响依计算结果而定。| |xor | OF=0,CF=0;对 SF、ZF 和 PF 依计算结果而定;对 AF 的影响未定义。|  ##实模式下的中断向量表 256个中断,每个在中断向量表中占2个字,分别是中断处理程序的偏移和逻辑段地址,从物理地址0x00000开始到0x003ff结束,共1KB,就是中断向量表(Interrupt Vector Table, IVT)。 利用中断向量表可以为所有的中断类型自定义中断处理过程,包括内部中断、硬件中断和软中断 | | | | :------------: | ------------ | |中断类型 |功能 | |一 CPU中断类型<br> 0 <br> 1<br> 2<br> 3<br> 4<br> 5<br> 6,7 </p>|<br>除法溢出中断<br>单步(用于DEBUG)<br>非屏蔽中断(NMI)<br>断点中断(用于DEBUG)<br>溢出中断<br>打印屏幕<br>保留</p>| |二 8259A中断类型<br> 8<br> 9<br> A<br> B<br> C<br> D<br> E<br> F</p>|<br>定时器(IRQ0)<br>键盘(IRQ1)<br>彩色/图形(IRQ2)<br>串行通信COM2(IRQ3)<br>串行通信COM1(IRQ4)<br>硬磁盘(IRQ5)<br>磁盘控制器中断(IRQ6)<br>并行打印机(IRQ7)</p>| |三 BIOS中断类型<br> 10 <br> 11 <br> 12 <br> 13 <br> 14<br> 15 <br> 16<br> 17<br> 18<br> 19<br> 1A</p>|<br>视频显示I/O<br>设备检验<br>测定存储器容量<br>磁盘I/O<br>RS-232-C 串行口I/O<br>系统描述表指针<br>键盘I/O<br>打印机<br>ROM<br>引导装入程序<br>日时钟</p>| |四 提供用户的中断类型<br> 1B <br> 1C</p>|<br>Ctrl+Break控制的软中断<br>定时器控制的软中断</p>| |五 数据表指针中断类型<br> 1D<br> 1E<br> 1F</p>|<br>视频参数块<br>软盘参数块<br>图形字符扩展码</p>| |六 DOS中断类型<br> 20 <br> 21 <br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 2A<br> 2E<br> 2F<br> 30~3F</p>|<br>DOS中断返回<br>DOS系统功能调用<br>程序终止时DOS返回地址(用户不能直接调用)<br>Ctrl+Break处理地址(用户不能直接调用)<br>严重错误处理(用户不能直接调用)<br>绝对磁盘读功能<br>绝对磁盘写功能<br>终止并驻留程序<br>DOS安全使用<br>快速写字符<br>Mircrosoft网络接口<br>基本SHELL程序装入<br>多路服务中断<br>DOS保留</p>| |七 BASIC中断类型<br> 40~5F<br> 60~67<br> 68~85<br> 86~F0<br> F1~FF</p>|<br>保留<br>用户软中断<br>保留<br>BASIC中断<br>保留</p>| ##保护模式下的中断和异常向量分配  ##中断与异常 INTEL处理器允许256个中断,中断号的范围是0~255 中断分为 一、 硬中断 - NMI:从NMI引脚来的中断信号称为非屏蔽中断(NonMaskable Interrupt, NMI),所有模式下NMI被赋予了统一的中断号2,必须立即处理的如ups要断电了发出中断,内存校验错误,处理器再努力工作也是没有意义的。 处理器不能屏蔽,但外部可屏蔽,CMOS RAM0x70端口指定单元时顺带设置最高位7是NMI中断的开关:0允许NMI 1阻断 - INTR:从INTR输入的中断信号叫作可屏蔽中断(Interrupt Request),8259负责15个(级联两块,一块提供8个,级联占用一个),接在8259上的设备有PS/2键盘和鼠标、串行口、并行口、软磁盘驱动器、IDE硬盘等,允许灵活设置中断号。 可屏蔽中断是否处理,先看处理器内部,标志寄存器IF,IF为0时,INTR中断信号都忽略;当其为1时,接受和响应中断,再看在8259芯片内部,有8位中断屏蔽寄存器(Interrupt Mask Register,IMR),对应着8个中断输入引脚,0允许,1阻断 二、 软中断 - 软中断是程序发出的中断处理,如int imm8。 - BIOS中断,最有名的软中断是实模式下的BIOS中断,电脑加电后,BIOS程序执行期间建立起来的,在加载和执行主引导扇区之前,就已经可以使用了。 三、 异常(处理器内部中断) - 第一种是指令执行异常,或者叫程序错误异常,如遇到非法指令时将产生中断6,除数为0引发0号中断 - 第二种是程序调试异常,通常由into、int3和bound指令主动发起 - 第三种是机器检查异常,如:总线错误、奇偶校验错误、高速缓存错误 根据异常情况的性质和严重性,又分为三种 - 故障(Faults)。故障通常是可以纠正的,比如P=0,段或页不在内存中 - 陷阱(Traps)。陷阱通常用于调试目的,比如单步中断指令int3和溢出检测指令into。 - 终止(Aborts)。终止标志着最严重的错误,诸如硬件错误、系统表(GDT、LDT等)中的数据不一致或者无效,内核通常从系统中抹去对应任务 ###屏蔽NMI示例、读RTC数据示例 ``` ;屏蔽NMI示例 读RTC数据示例 .w0: mov al,0x0a ;指定寄存器A or al,0x80 ;7位置1,阻断NMI,测试用,通常是不必要的 out 0x70,al in al,0x71 ;读寄存器A test al,0x80 ;测试第7位UIP ,uip为1时,0x00-0x09日期时间不能访问 jnz .w0 ;uip位为0时,才能向下执行读时间日期等 ``` ###修改IMR屏蔽可屏蔽中断INTR ``` 样例一: MOV AL, 11111100B OUT 屏蔽寄存器(IMR)的口地址, AL ;屏蔽 IRR7 ~ IRR2 的中断请求, 只开放 IRR1,IRR0 的中断请求 样例二: in al,0xa1 ;读8259从片的IMR寄存器 and al,11111110B ;IR0允许中断(此位连接RTC) out 0xa1,al ;写回此寄存器 ``` ##8259A芯片实时时钟RTC > 实模式下主片IR0-IR7默认分别对应中断号0x08-0x0f,保护模式下因系统占用与保留了前0x20的中断号,所以必须重新指定,可指定为0x20~0x27       ###ICW命令字 **深色部分为被保留或者不用使用固定值,其它部分位设置成比较通用的配置**  ###修改8259A芯片中断号 - 重新初始化8259A芯片的原因是其主片的中断向量和处理器的异常向量冲突。计算机启动之后,主片的中断向量为0x08~0x0F在保护模式中被用作异常向量。 - 初始化时对于主片来说,需要先向0x20端口发送ICW1,对从片来说端口是0xA0,每当8259A接到ICW1意味着一个新的初始化开始。 - 接受ICW1后,8259A期待从0x21/0xA1接受ICW2,但是它是否期待ICW3和ICW4要看ICW1的内容。ICW1位0决定是否有ICW4,位1指示是否为多片级联,如果是必定有ICW3命令。这样就知道,是否还要在端口(0x21/0xA1)上依次再接受ICW3和ICW4。 ``` ;修改8259A的主片中断号从0x20-0x27(对应IR0-IR7) mov al,0x11 ;ICW1为0001 0001 out 0x20,al ;0x20为端口,设置ICW1:边沿触发/级联方式/有ICW4 mov al,0x20 ;ICW2为0010 0000,起始中断号 out 0x21,al ;设置ICW2:起始中断向量 mov al,0x04 ;ICW3为0000 0100,2号位为级联位 out 0x21,al ;设置ICW3:IR2位级联到从片 mov al,0x01 ;ICW4为0000 0001, out 0x21,al ;ICW4:非总线缓冲,全嵌套,正常EOI ;修改8259A的从片中断号从0x70-0x77(对应IR0-IR7) mov al,0x11 ;ICW1为0001 0001 out 0xa0,al ;0xa0为端口,设置ICW1:边沿触发/级联方式/有ICW4 mov al,0x70 ;ICW2为0111 0000,起始中断号 out 0xa1,al ;设置ICW2:起始中断向量 mov al,0x02 ;ICW3为0000 0010,从片级联到主片IR2,2号位 out 0xa1,al ;设置ICW3 mov al,0x01 ;ICW4为0000 0001, out 0xa1,al ;ICW4:非总线缓冲,全嵌套,手动EOI ``` ###中断结束命令EOI 在8259内部有个8位中断服务寄存器(Interrupt ServiceRegister, ISR),每位对应着一个中断引脚,正在处理中断服务中,中断相应位置1,如果不清除,下次中断将得不到处理,需要显式清除,中断结束命令的代码是0x20,如果是主片那么,EOI(End Of Interrupt)命令仅发给主片,端口号是0x20;如果是从片,主从都发。 ``` ;可以在中断处理程序首部加入 应当是清除所有正在处理中断服务标志 mov al,0x20 ;清除中断标志 中断结束命令EOI out 0xa0,al ;向8259A从片发送 out 0x20,al ;向8259A主片发送 ``` ##与任务相关的,各种描述符 ###与任务相关各部分逻辑关系  ###任务切换的方法 - 总体上任务切换有两种方式,一种是处理器硬件执行任务切换,一种是软件自己执行任务切换。硬件任务切换被32位处理器的固件支持,但流行的操作系统并不使用,因为它比较费时,大体掌握即可。 - 硬件切换,只要给出新任务的(TSS或任务门)选择子。简单但是处理器要各种检查非常耗时,因此在现实中除非传统的保护模式下32位程序,64位不再支持硬件切换。 1. 第一种硬件切换是借助于中断,这是现代抢占式多任务的基础。如果中断号对应的是任务门,进行硬件切换。也可以在中断处理过程中执行任务切换,但这由内核实施的,不是由处理器固件进行的。 中断任务门硬件切换流程:中断号乘8访问中断描述符表,当为任务门先查p位,cpu再进行硬件切换,先从任务门描述符中取出TSS选择子,用它从GDT取出TSS描述符,检查B要为0,然后把当前任务状态保存到TSS,再从新任务的TSS中恢复各个通用寄存器、EFLAGS、段寄存器、EIP、ESP,LDTR等,最终TR指向新任务的TSS,开始执行新任务,此时自动将新任务TSS描述符的B位置1标记为忙,同时把老任务TSS选择子写到新任务TSS链中,同时将新任务EFLAGS的NT位置1,通过NT位区别任务切换与常规中断返回 2. 第二种call far和jmp far指令通过TSS描述符选择子或任务门发起任务切换,类似于中断,由call发起的任务切换是嵌套的,而jmp不会形成嵌套任务。call可以形成多级嵌套,通过iret返回前一任务。 jmp far处理器硬件切换流程,检查新任务TSS描述符:P位1(TSS是否在内存中)、界限值、B位0(任务不忙),旧任务清除B位,保存它的状态到TSS中,包括通用寄存器、EFLAGS、段寄存器(16位部分)、EIP、ESP。接下来新任务:设置的B位1,加载TR,载入新任务状态。如果是第一次切换,其入口点就在其TSS配置中的cs:eip,否则为上次中断的保存中的断点。 3. 第三种可以使用iret指令从当前任务返回(切换)到前一个任务,前提是当前任务的EFLAGS的NT位必须是1 ###32位硬件任务切换详细流程 jmp、call、iret指令或者异常和中断,是程序重定向的机制,它们所引用的TSS描述符或者任务门,以及寄存器EFLAGS NT标志的状态,决定了任务是否切换,以及如何发生。 在任务切换时,处理器执行以下操作: 一、从jmp或者call指令的操作数、任务门或者当前任务的TSS任务链接域取得新任务的TSS描述符选择子。 二、检查是否允许从当前任务(旧任务)切换到新任务。数据访问的特权级检查规则适用于jmp和call指令,当前(旧)任务的CPL和新任务段选择子的RPL必须在数值上小于或者等于目标TSS或者任务门的DPL。异常、中断(除了以int n指令引发的中断)和iret指令引起的任务切换忽略目标任务门或者TSS描述符的DPL。对于以int n指令产生的中断,要检查DPL。 三、检查新任务的TSS描述符是否已经标记为有效(P=1),并且界限也有效(大于或者等于0x67,即十进制的103)。 四、检查新任务是否可用,不忙(B=0,对于以call、jmp、异常或者中断发起的任务切换)或者忙(B=1,对于以iret发起的任务切换)。 五、检查当前任务(旧任务)和新任务的TSS,以及所有在任务切换时用到的段描述符已经安排到系统内存中。 六、如果任务切换是由jmp或者iret发起的,处理器清除当前(旧)任务的忙(B)标志;如果是由call指令、异常或者中断发起的,忙(B)标志保持原来的置位状态。 七、如果任务切换是由iret指令发起的,处理器建立EFLAGS寄存器的一个临时副本并清除其NT标志;如果是由call指令、jmp指令、异常或者中发起的,副本中的NT标志不变。 八、保存当前(旧)任务的状态到它的TSS中。处理器从任务寄存器中找到当前TSS的基地址,然后将以下寄存器的状态复制到当前TSS中:所有通用寄存器、段寄存器中的段选择子、刚才那个寄存器EFLAGS的副本,以及指令指针寄存器EIP。 九、如果任务切换是由call指令、异常或者中断发起的,处理器把从新任务加载的寄存器EFLAGS的NT标志置位;如果是由iret或者jmp指令发起的,NT标志位的状态对应着从新任务加载的寄存器EFLAGS的NT位。 十、如果任务切换是由call指令、jmp指令、异常或者中断发起的,处理器将新任务TSS描述符中的B位置位;如果是由iret指令发起的,B位保持原先的置位状态不变。 十一、用新任务的TSS选择子和TSS描述符加载任务寄存器TR。 十二、新任务的TSS状态数据被加载到处理器。这包括寄存器LDTR、 PDBR(控制寄存器CR3)、寄存器EFLAGS、寄存器EIP、通用寄存器,以及段选择子。载入状态期间只要发生一个故障,架构状态就会被破坏(因为有些寄存器的内容已被改变,而且无法撤销和回退)。所谓架构,是指处理器对外公开的那一部分的规格和构造;所谓架构状 态,是指处理器内部的各种构件,在不同的条件下,所建立起来的确定状态。当处理器处于某种状态时,再施加另一种确定的条件,可以进入另一种确定的状态,这应当是严格的、众所周知的、可预见的。否则,就意味着架构状态遭到了破坏。 十三、与段选择子相对应的描述符在经过验证后也被加载。与加载和验证新任务环境有关的任何错误都将破坏架构状态。注意,如果所有的检查和保护工作都已经成功实施,处理器提交任务切换。如果在从第1步到第11步的过程中发生了不可恢复性的错误,处理器不能完成任务切换,并确保处理器返回到执行发起任务切换的那条指令前的状态。如果在第12步发生了不可恢复性的错误,架构状态将被破坏;如果在提交点(第13步)之后发生了不可恢复性的错误,处理器完成任务切换并在开始执行新任务之前产生一个相应的异常。 十四、开始执行新任务。 在任务切换时,当前任务的状态总要被保存起来。在恢复执行时,处理器从寄存器EIP的保存值所指向的那条指令开始执行,这个寄存器的值是在当初任务被挂起时保存的。 任务切换时,新任务的特权级别并不是从那个被挂起的任务继承来的。新任务的特权级别是由其段寄存器CS的低2位决定的,而该寄存器的内容取自新任务的TSS。因为每个任务都有自己独立的地址空间和任务状态段TSS,所以任务之间是彼此隔离的,只需要用特权级规则控制对TSS的访问就行,软件不需要在任务切换时进行显式的特权级检查。 ###8种描述符 - 通过S位与TYPE区分,除了最后两种:代码段描述符与数据段描述符,其它s=1为系统描述符。 - 四种门描述符共用一例程来生成,余下四个段可共用一例程生成。 - 中断门和陷阱门描述符只允许存放在IDT内,任务门可以位于GDT、LDT和IDT中,调用门可以位于GDT、LDT中,TSS与LDT位于GDT中。   ###段描述符  **代码段根据段界限、G粒度得出物理界限,数据栈段还得考虑type中的E扩展方向得物理界限** - G 位,0:字节,1:4KB,段界限粒度(Granularity)是字节(1B~1MB)还是4KB(4KB~4GB)为单位 - D/B: 0:16位宽 1:32位宽, “默认的操作数大小”(Default Operation Size)或者“默认的栈指针尺寸”(Default Stack Pointer Size),代码段使用16位IP还是EIP,对堆栈段来说叫做“B”位,对应SP与ESP。 - L 位是 64 位代码段标志(64-bit Code Segment) - AVL 是软件可以使用的位(Available) - P位:0:不存在 1:在内存中, 段存在位(Segment Present),对应的段是否在于内存中,有些内容在虚拟内存中 - DPL 表示描述符的特权级(Descriptor Privilege Level,DPL)占两位共有4种0、1、2、3,访问该段必须有的最低特权级 - S:0表示系统段;1表示代码段或数据段(堆栈段是特殊数据段) 用于指定描述符的类型(Descriptor Type)。 - TYPE字段共4位,是描述符的子类型,如下图  - X表示是否可以执行(eXecutable) - E=0是向上扩展的,高地址 - W=0的段是不允许写入 - C位特权级依从(Conforming)。C=0表示非依从的代码段,与它同特权级的代码调用或者通过门调用;C=1表示允许从低特权级的程序转移到该段执行。 - R位指示代码段是否允许读出,R=0不能读出,R=1可读,如使用段超越前缀“CS:”来访问代码段中的内容。 - A位是已访问(Accessed)位,最近是否被访问过,创建时清零,之后每当访问时处理器自动置1,清零是由内核负责,通过监视该位,就可统计出该段的使用频率 如80*25字符显存缓冲: 0x0040920b 0x8000ffff 线性基地址32位为 0x000B8000。 段界限20位为 0x0FFFF,粒度为字节(G=0)。即,该段的长度为 64KB。 属于代码段或数据段(S=1)。 这是一个 32 位的段(D=1)。 该段目前位于内存中(P=1)。 段的特权级为 0(DPL=00)。 这是一个可读可写、向上扩展的数据段(TYPE=0010)。 ###段选择子 - **段选择子**传送到段寄存器的是段选择子,2^13=8192所以描述符索引只要13位就够了 - **TI**是描述符表指示器(Table Indicator),TI=0描述符在GDT中;TI=1描述符在LDT中。 - **RPL**是请求特权级  - **LDT**:与GDT类似,是进程(任务)对应的Local Descriptor Table,局部描述符表,与GDT不同的是0号槽位可用,LDT使用LDTR寄存器 ###CPL、RPL、DPL特权级 - **CPL**当前代码段(CS中)的特权级叫作当前特权级(Current Privilege Level) - **RPL** 段选择子中的RPL,表示给出当前选择子的那个程序的特权级别,如果是传参,那么RPL为调用程序的特权级 - **DPL** 描述符的特权级 ###GDT与GDTR寄存器 - **GDT全局描述符表**(Global Descriptor Table),所有的段描述符都是挨在一起集中存放的构成描述符表,共2^16=64K,65536/8=8192(最多)。GDT中的第一个描述符必须是空描述符,或者叫“哑描述符”、NULL描述符  - **GDTR**,处理器有一个48位的全局描述符表寄存器。该寄存器分为两部分,分别是32位的线性地址和16位的边界,分别对应GDT的起始地址与已有段描述符的边界,因为段边界为16位,所以全局描述符表占最多2^16=64Kb。  ###LDT描述符与LDTR寄存器  D位(或者叫B位)和L位对LDT描述符来说没有意义,固定为0 S位固定为0,表示系统的描述符 ###TSS描述符与TR寄存器  TSS描述符的格式和LDT描述符差不多,除了TYPE位 TYPE位中的B位是“忙”位(Busy)。在任务刚刚创建的时候,它为1001,即B位是0表明任务不忙。当任务开始执行时或者处于挂起状态(临时被中断执行)时,由处理器固件把B位置1,可以防止重入的就是不能从自己切换到自己  ###TSS任务状态段 TSS任务状态段(Task StateSegment)在多任务的环境中,当任务切换时,必须保护现场到一个内存区域,包括通用寄存器、段寄存器、栈指针寄存器ESP、指令指针寄存器EIP、状态寄存器EFLAGS等等。TSS具有固定的格式,最小尺寸是104字节。  偏移0处是前一个任务的TSS描述符选择子,安装在全局描述符表GDT中,用来记录和追踪前一个任务 SS0、SS1和SS2与ESP0、ESP1和ESP2分别是0、1和2特权级栈与指针,由任务的创建者填写,特权级控制转移时,用来切换栈 32-92为寄存器的快照,进行任务切换时保存状态以便将来恢复现场。在多任务环境中每创建一个任务内核至少要填写EIP、EFLAGS、ESP、CS、SS、DS、ES、FS和GS,第一次执行时从这里加载初始执行环境,并从CS:EIP处开始执行任务。在此之后快照由处理器固件进行更改 LDT描述符选择子由内核填写,该信息由处理器在任务切换时使用 T位用于软件调试。在多任务的环境中如果T位是1,每次切换到该任务时,将引发一个调试异常中断。 I/O映射基地址指向I/O许可位串,决定可以访问的端口,当前任务的CPL<=IOPL(EFLAGS状态寄存器),所有端口可以访问。个别端口的访问就要检索I/O许可位串,处理器可以访问65536个端口,就对应65536个位,相应位为0允许访问。65536/8=8192=最多需要8K I/O映射基地址从TSS的起始处(0)算起。因此,如果该字单元的内容大于等于TSS的段界限(在TSS描述符中),则表明没有I/O许可位串  因为I/O端口是按字节编址的,当以字或者双字访问时,实际上是访问连续的2个或者4个端口,如:in ax,0x3f8,实际从0x3f8,0x3f9端口读数据,权限检查时这两端口不在同一字节内,所以处理器每次都要从I/O许可串读连续的2字节,也因为此,如果要检查的比特在最后一字节中,那么读这2字节的将会越界,为防止这种情况,所以要求它最后一字节所有比特都是“1”,即0xFF。  ###中断描述符表IDT - 保护模式用中断描述符表取代中断向量表存放中断门、陷阱门和任务门。 - 中断门与陷阱门为任务内控制转移,任务门得切换任务,都用iret指令返回 - 中断发生时中断号乘8访问中断描述符表,取出门描述符,内含代码段选择子和段内偏移量,转去执行。 - 一般的中断处理使用中断与陷阱门,它们与调用门相同,转至任务全局空间去执行系统级工作,都是任务内的控制转移。 处理器中有个48位的中断描述符表寄存器(Interrupt Descriptor Table Register, IDTR),保存着32位线性基地址和16位界限,与GDT一样。为性能最大化建议IDT基地址是8字节对齐。处理器复位时IDTR的基地址0,界限0xFFFF。16位的表界限意味着IDT和GDT、LDT一样,表的大小可以是64KB,事实上因为处理器只能识别256种中断,故通常只使用2KB。 ###调用门描述符 任务内转移,转到任务内全局空间执行,当前权限小于目标代码使用,调用门(Call-Gate)描述符可以安装在GDT或LDT中,用调用门选择子替换高权限的段选择子:偏移 调用规则(在数值上): - CPL与RPL<=调用门描述符DPL,即权限大于描述符的 且 - CPL>=目标代码段描述符DPL,即权限小于目标代码 **通过调用门控制转移时,使用jmp far(不改所以只能同级调用),或call far(改变当前特权级CPL),retf时恢复。因为特权级不一致所以还要切换栈**  **P**位是有效位,通常应该是“1”。当它为“0”时,产生异常中断 **DPL** 等于高于此特权级才能调用,数值<=调用门的DPL **TYPE** 值“1100”表示调用门 调用门描述符中有一些字段没有使用,固定为“0” ###任务门描述符  - P位为“0”时,不允许通过此门实施任务切换 - DPL是任务门描述符的特权级,但是对因中断而发起的任务切换不起作用 任务门描述符中当P位为0,不允许任务切换,DPL是此门特权级(DPL对中断不起作用) 任务门描述符可以安装在GDT与LDT中 ###中断门描述符 > 只能转到大于等于自身特权级的中断处理代码段中(数值上CPL>=目标代码DPL),只能低到高 > 软中断还检查门特权,数值上CPL<=门描述符DPL, 当前权限要高于等于门权限 > 在中断处理过程中,特权级提升,如果CPL发生了改变,栈就必须切换。  - DPL 高于等于此特权级才能调用,数值<=调用门的DPL ###陷阱门描述符 ###IDTR中断描述符表寄存器  ##页部件 ###页目录项和页表项的组成  - P(Present)是存在位,为“1”时,表示页表或者页位于内存中。否则,表示页表或者页不在内存中,必须先予以创建,或者从磁盘调入内存后方可使用。 - RW(Read/Write)是读/写位。为“0”时表示这样的页只能读取,为“1”时,可读可写。 - US(User/Supervisor)是用户/管理位。为“1”时,允许所有特权级别的程序访问;为“0”时,只允许特权级别为0、1和2的程序访问,特权级别为3的程序不能访问。 - PWT(Page-level Write-Through)是页级通写位,和高速缓存有关。“通写”是处理器高速缓存的一种工作方式,这一位用来间接决定是否采用此种方式来改善页面的访问效率。 - PCD(Page-level Cache Disable)是页级高速缓存禁止位,用来间接决定该表项所指向的那个页是否使用高速缓存策略。 - A(Accessed)是访问位。该位由处理器固件设置,用来指示此表项所指向的页是否被访问过。这一位很有用,可以被操作系统用来监视页的使用频率,当内存空间紧张时,用以将较少使用的页换出到磁盘,同时将其P位清零。然后,将释放的页分配给马上就要运行的程序,以实现虚拟内存管理功能。 - D(Dirty)是脏位。该位由处理器固件设置,用来指示此表项所指向的页是否写过数据。 - PAT(Page Attribute Table)页属性表支持位。此位涉及更复杂的分页系统,和页高速缓存有关,可以不予理会,在普通的4KB分页机制中,处理器建议将其置“0”。 - G(Global)是全局位。用来指示该表项所指向的页是否为全局性质的(比如,属于所有任务共有的内核部分)。如果页是全局的,那么,它将在高速缓存中一直保存(也就意味着地址转换速度会很快)。因为页高速缓存容量有限,只能存放频繁使用的那些表项。而且,当因任务切换等原因改变寄存器CR3的内容时,整个页高速缓存的内容都会刷新。 - AVL位被处理器忽略,软件可以使用 ###地址变换的具体过程  ###多任务环境下的页目录表和页表映射  ###切换任务时页部件变化  ##x86汇编语言:从实模式到保护模式 ###20章TCB  ###内存布局   ###任务控制块TCB与TCB链   ###GDT分布  #一个64位操作系统的设计与实现 ##内存分布 ``` |----------------------| | 100000 ~ END | | KERNEL | |----------------------| | E0000 ~ 100000 | | Extended System BIOS | |----------------------| | C0000 ~ Dffff | | Expansion Area | |----------------------| | A0000 ~ bffff | | Legacy Video Area | |----------------------| | 9f000 ~ A0000 | | BIOS reserve | |----------------------| | 90000 ~ 9f000 | | kernel tmpbuf | |----------------------| | 10000 ~ 90000 | | LOADER | |----------------------| | 8000 ~ 10000 | | VBE info | |----------------------| | 7e00 ~ 8000 | | mem info | |----------------------| | 7c00 ~ 7e00 | | MBR (BOOT) | |----------------------| | 0000 ~ 7c00 | | BIOS Code | |----------------------| ``` #有用的代码段 ##测试大小端 ``` ;测试大小端 mov ax,0xb800 ;显存段地址存入ds mov es,ax mov byte [es:0x00],'a' ;要显示的字符存入显存 mov byte [es:0x02],'b' ;高位不写默认0x07,背景黑0000前景白0111。 mov word [0],0x0102 ;存入测试大小端 mov al,[0] ;显示低端 add al,0x30 mov [es:0x04],al jmp $ ;$为本行偏移地址,死循环 times 510-($-$$) db 0 ;用0补足512字节,$$为起始偏移地址 因为一共为512字节,512-2-(当前偏移-0) db 0x55,0xaa ;如果其是有效的引导扇区,最后2字节应当是0x55和 ``` ##清屏 ``` ;清屏 mov cx,2000 mov ax,0xb800 mov ds,ax mov bx,0x0700 xor si,si cls: mov [si],bx add si,2 loop cls ``` ``` ;清屏 mov cx,2000 mov ax,0xb800 mov ss,ax mov bx,0x0700 mov sp,4000 cls:push bx loop cls ``` ##显示字符串 ``` ; 用A-H分别填充0-7页,0页全是A,类推,调用函数显示第N页缓冲,就是把第N页copy到0页 ; 每页4K,4096,10000 0000 0000 mov ax,0x7c00 mov sp,ax mov ax,0xb800 ; 显存缓存的起始地址 mov ds,ax ; 设置段寄存器es为显存缓存的段地 mov di,0 ;显示位置 mov cx,32768/2 ;循环次数 mov bx,0x0741 ;显示内容 fill: mov [di],bx add di,2 ;如果翻页di能被4096整除bx++ 显示A-H test di,1111_1111_1111B jnz conti inc bx conti: loop fill mov ax,7 call page sti hlt1: hlt jmp hlt1 ;page为独立的函数 显示哪一页缓冲 b8000+4096起对应1页-7页 page: ;ax=要显示的页数1-7 pusha mov bx,0xb800 ; 显存缓存的起始地址 mov ds,bx ; 设置段寄存器为显存缓存 mov es,bx mov si,4096 mul si cld mov si,ax mov di,0x00 mov cx,2000 rep movsw popa ret times 510-($-$$) db 0 db 0x55,0xaa ``` ``` ;默认模式下 利用内存映射输出文字 ;功能描述:在Teletype模式(开机默认模式下80*25)下显示字符 ;显存起始位置0xb8000 ;显示前要清屏,回车换行都换行,或自己处理 MOV AX,0x7c0 MOV DS,AX MOV AX,0xB800 MOV ES,AX MOV SI,msg XOR DI,DI ;显示起始位置 putloop: MOV AL,[SI] CMP AL,0 JE fin ; 如果已经将要输出的字符全部输出完了,则跳转到fin处 CMP AL,0x0d JE enter ; 如果是回车简单处理n=(DI/160+1)*160 CMP AL,0x0a JE enter ; 如果是换行简单处理n=(DI/160+1)*160 MOV [ES:DI],AL ; 显示字符 INC SI ADD DI,2 ; 本来是高位为背景与前景设置,低位ascll码, 这里高位用默认 JMP putloop ; 继续输出 enter: MOV BL,160 MOV AX,DI DIV BL ADD AL,1 MUL BL MOV DI,AX INC SI JMP putloop ; 继续输出 fin: HLT ; 让CPU停止 等待指令 JMP fin ; 死循环 msg: DB "hello, world!" ; 要输出的字符 DB 0x0d ; 回车换行 DB "hello, world!" ; 要输出的字符 DB 0x0a ; 换行 DB "hello, world!" ; 要输出的字符 DB 0x0a ; 换行 DB 0 ; 结束输出的标识 times 510-($-$$) DB 0 DB 0x55,0xaa ``` ``` ; INT 0x10 中断:对屏幕及显示器所提供的服务程序 ; 使用该中断需指定 AH 寄存器编号,不同编号又有不同寄存器对应的参数 ; AH = 13h, 在 teletype 模式下显示字符串 ; 入口参数: ; AL = 显示方式 ; 0: 不移动光标,属性在 BL 中 ; 1: 移动光标,属性在 BL 中 ; 2: 不移动光标,字符串中包含属性 ; 3: 移动光标,字符串中包含属性 ; BH = 页码 ; BL = 属性 ; CX = 字符串长度 ; DH = 行 ; DL = 列 ; ES:BP = 指向字符串 ; 出口参数:无 MOV AX, 0x7c0 ; 设置 ES 段的段地址 MOV ES, AX MOV BP, message ; ES:BP 指向字符串 MOV AX, 0x1301 MOV BX, 0x0007 MOV DX, 0x1200 MOV CX, 5 ; 字符串长度 INT 0x10 ; 中断调用 JMP $ ; 跳转到当前地址,也就是死循环 message db 'TEST ' ;字符串任意,但是不要超过5个字符 times 510-($-$$) db 0 db 0x55,0xaa ``` ``` ;默认模式下 中断输出文字 ;功能描述:在Teletype模式(开机默认模式下80*25)下显示字符 ;入口参数:AH=0EH ;AL=字符 ;BH=页码 ;BL=前景色 ;INT 10H MOV AX,0x7c0 MOV DS,AX MOV SI,msg putloop: MOV AL,[SI] ; AL中存放要显示的字符 ADD SI,1 ; SI加1 CMP AL,0 JE fin ; 如果已经将要输出的字符全部输出完了,则跳转到fin处 MOV AH,0x0e MOV BX,15 ; bh = 0 bl为配色方案 INT 0x10 ; 调用显卡BIOS JMP putloop ; 继续输出 fin: HLT ; 让CPU停止 等待指令 JMP fin ; 死循环 msg: DB "hello, world!" ; 要输出的字符 DB 0x0d,0x0a ; 回车与换行 正常 DB "hello, world!" ; 要输出的字符 DB 0x0a, 0x0a ; 换行2次,有问题 DB "hello, world!" ; 要输出的字符 DB 0x0a ; 换行1次,正常 DB "hello, world!" ; 要输出的字符 DB 0x0d ; 回车,有问题 DB "hello, world!" ; 要输出的字符 DB 0x0a ; 换行 DB 0 ; 结束输出的标识 times 510-($-$$) DB 0 DB 0x55,0xaa ``` ``` ;从光标处显示字符串 [ds:bx]指向要显示的串,0x0结束 \r\n换行 SECTION code_1 align=16 vstart=0 ;定义代码段1(16字节对齐) ;------------------------------------------------------------------------------- start: mov ax,1000h ;设置到用户程序自己的堆栈 非必需 mov ss,ax mov sp,0 mov ax,section.data_1.start+7c00h ;设置到数据段 [ds:bx]指向要显示的串,0x0结束 shr ax,4 mov ds,ax mov bx,msg0 call put_string ;显示第一段信息 jmp $ ;------------------------------------------------------------------------------- put_string: ;显示串(0结尾)。 ;输入:DS:BX=串地址 mov cl,[bx] or cl,cl ;cl=0 ? jz .exit ;是的,返回主程序 call put_char inc bx ;下一个字符 jmp put_string .exit: ret put_char: ;显示一个字符 ;输入:cl=字符ascii push ax push bx push cx push dx push ds push es ;以下取当前光标位置 mov dx,0x3d4 mov al,0x0e out dx,al mov dx,0x3d5 in al,dx ;高8位 mov ah,al mov dx,0x3d4 mov al,0x0f out dx,al mov dx,0x3d5 in al,dx ;低8位 mov bx,ax ;BX=代表光标位置的16位数 cmp cl,0x0d ;回车符? jnz .put_0a ;不是。看看是不是换行等字符 mov ax,bx ;此句略显多余,但去掉后还得改书,麻烦 mov bl,80 div bl mul bl mov bx,ax jmp .set_cursor .put_0a: cmp cl,0x0a ;换行符? jnz .put_other ;不是,那就正常显示字符 add bx,80 jmp .roll_screen .put_other: ;正常显示字符 mov ax,0xb800 mov es,ax shl bx,1 mov [es:bx],cl ;以下将光标位置推进一个字符 shr bx,1 add bx,1 .roll_screen: cmp bx,2000 ;光标超出屏幕?滚屏 jl .set_cursor push bx mov ax,0xb800 mov ds,ax mov es,ax cld mov si,0xa0 mov di,0x00 mov cx,1920 rep movsw mov bx,3840 ;清除屏幕最底一行 mov cx,80 .cls: mov word[es:bx],0x0720 add bx,2 loop .cls pop bx sub bx,80 .set_cursor: mov dx,0x3d4 mov al,0x0e out dx,al mov dx,0x3d5 mov al,bh out dx,al mov dx,0x3d4 mov al,0x0f out dx,al mov dx,0x3d5 mov al,bl out dx,al pop es pop ds pop dx pop cx pop bx pop ax ret ;=============================================================================== SECTION data_1 align=16 vstart=0 msg0 db ' This is NASM - the famous Netwide Assembler. ' db 'Back at SourceForge and in intensive development! ' db 'Get the current versions from http://www.nasm.us/.' db 0x0d,0x0a,0x0d,0x0a db ' jle @@',0x0d,0x0a db ' ... ...(Some other codes)',0x0d,0x0a,0x0d,0x0a db 0 ;=============================================================================== times 510-($-$$)-0c0h db 0 db 0x55,0xaa ``` ##用端口操作硬盘LBA28模式 LBA28模式,用28位地址来读写逻辑扇区,2^28*512=128GB/一块硬盘 分主接口与副接口,每个接口可挂两个硬盘主盘与从盘共4个,主从区分与设置起始扇区一起设置 主接口的端口是0x1f0~0x1f7,副接口的端口是0x170~0x177,全部8位端口 ``` ;读硬盘,从逻辑扇区0读一个扇区到ds:bx=1000H:0, s_start_height equ 0x0000 ;起始扇区最大28位,高16位 s_start_lower equ 0x0000 ;低16位 s_num equ 1 ;读几个扇区8位,0x00-0xff,0为256 ds_read equ 0x1000 ;读入ds:bx bx_read equ 0 ;第1步,0x1f2端口设置读扇区数,8位端口最大256,0x00-0xff,0为256。 mov dx,0x1f2 mov al,s_num out dx,al ;第2步,设置起始LBA扇区号,连续读写,28位扇区号分成4段,分别写入端口0x1f3写入0~7位,0x1f4写入8~15位,0x1f5写入16~23位,0x1f6的0~3位存放逻辑扇区号的24~27位,第4位0为主盘,1从盘,5~7位是111表示LBA模式。起始扇区2 inc dx ;0x1f3 mov ax,s_start_lower ;起始扇区,低8位 out dx,al ;LBA地址7~0 inc dx ;0x1f4 mov al,ah out dx,al ;LBA地址15~8 inc dx ;0x1f5 mov ax,s_start_height out dx,al ;LBA地址23~16 inc dx ;0x1f6 mov al,0xe0 ;LBA28模式,主盘 or al,ah out dx,al ;第3步,向端口0x1f7写入0x20,请求硬盘读 mov dx,0x1f7 mov al,0x20 out dx,al ;第4步,等待硬盘就绪执行数据传输。端口0x1f7既是命令端口,又是状态端口。0x1f7端口的7位为占用状态1忙,忙完后置为0,同时将3位置1意思是准备好了,请求主机发送或者接收数据 .waits: in al,dx and al,0x88 ;读7位与3位 cmp al,0x08 ;状态为准备好了 jnz .waits ;不忙了才向后执行数据传输 ;第5步,连续取出数据。0x1f0是16位数据端口,一旦硬盘空闲且准备就绪,就可以连续写入或者读取数据。下面的代码假定是从硬盘读一个扇区(512字节,或者256字),存放到由段寄存器DS指定的数据段,偏移地址由寄存器BX指定: mov ax,ds_read mov ds,ax mov bx,bx_read mov cx,s_num*512/2 ;总共要读取的字数 mov dx,0x1f0 .readw: in ax,dx mov [bx],ax add bx,2 loop .readw jmp $ ;$为本行偏移地址,死循环 times 510-($-$$) db 0 ;用0补足512字节,$$为起始偏移地址 因为一共为512字节,512-2-(当前偏移-0) db 0x55,0xaa ``` out请求硬盘读时端口0x1f7各位的含义  in时读取状态时各位的含义  #全部汇编指令功能说明 |指令|功能|说明| | ------------ | ------------ | ------------ | |AAA|未组合的十进制加法调整指令 AAA(ASCII Adgust for Addition)<br>格式: AAA<br>功能: 对两个组合的十进制数相加运算(存在AL中)的结果进行调整,产生一个未组合的十进制数放在AX中.|说明:<br>1. 组合的十进制数和未组合的十进制数:在计算中,十进制数可用四位二进制数编码,称为BCD码.<br>当一个节(8位)中存放一位BCD码,且放在字节的低4位, 高4位为时称为未组合的BCD码.<br>2. AAA的调整操作<br>若(AL) and 0FH>9 或 AF=1,则调整如下:<br>(AL)<--(AL)+6,(AH)<--(AH)+1,AF=1,CF<--AF,(AL)<--(AL) and 0FH| |AAD|未组合十进制数除法调整指令 AAD(ASCII Adjust for Division)<br>格式: AAD<br>功能: 在除法指令前对AX中的两个未组合十进制数进行调整,以便能用DIV指令实现两个未组合的十进制数的除法运算,其结果为未组合的十进制数,商(在AL中)和余数(在AH中).|说明:<br>1. AAD指令是在执行除法DIV之前使用的,以便得到二进制结果存于AL中,然后除以OPRD,得到的商在AL中,余数在AH中.<br>2. 示例: MOV BL,5<br>MOV AX,0308H<br>AAD ;(AL)<--1EH+08H=26H,(AH)<--0<br>DIV BL ;商=07H-->(AL),余数=03H-->(AH).| |AAM|未组合十进制数乘法调整指令 AAM(ASCII Adjust MULtiply)<br>格式: AAM<br>功能: 对两个未组合的十进制数相乘后存于AX中的结果进行调整,产生一个未组合的十进制数存在AL中.|说明:<br>1. 实际上是两个未组合的十进制数字节相乘,一个0~9的数与另一个0~9的数相乘其积最大为81.为了得到正确的结果,应进行如下调整:<br>乘积: (AH)<--(AL)/10<br>(AL)<--(AL)MOD10<br>2. 本指令应跟在MUL指令后使用,乘积的两位十进制结果,高位放在AH中,低位放在AL中.AH内容是MUL指令的结果被10除的商,即(AL)/10,而最后的AL内容是乘积被10整除的余数(即个位数).| |AAS|未组合十进制减法调整指令 AAS(ASCII Adjust for Subtraction)<br>格式: AAS<br>功能: 对两个未组合十进制数相减后存于AL中的结果进行调整,调整后产生一个未组合的十进制数数且仍存于AL中.|说明:<br>1. 本指令影响标志位CF及AF.<br>2. 调整操作<br>若(AL) and 0FH > 9 或 AF=1<br>则(AL)<--(AL)-6,(AH)<--(AH)-1,CF<--AF,(AL)<--(AL) and 0FH,<br>否则(AL)<--(AL) and 0FH| |ADC|带进位加法指令 ADC(Addition Carry)<br>格式: ADC OPRD1,OPRD2<br>功能: OPRD1<--OPRD1 + OPRD2 + CF|说明:<br>1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数.<br>OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数.<br>2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的,但不允许两个都是存储器操作数.<br>3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志.<br>4. 该指令对标志位的影响同ADD指令.| |ADD|加法指令 ADD(Addition)<br>格式: ADD OPRD1,OPRD2<br>功能: 两数相加|说明:<br>1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数.<br>OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数.<br>2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的, 但不允许两个都是存储器操作数.<br>3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志.加法指令适用于无符号数或有符号数的加法运算.| |AND|逻辑与运算指令 AND<br>格式: AND OPRD1,OPRD2<br>功能: 对两个操作数实现按位逻辑与运算,结果送至目的操作数.本指令可以进行字节或字的‘与’运算,<br>OPRD1<--OPRD1 and OPRD2.|说明:<br>1. 目的操作数OPRD1为任一通用寄存器或存储器操作数.源操作数OPRD2为立即数,任一通用寄存器或存储器操作数.<br>2. 示例: AND AL,0FH ;(AL)<--(AL) AND 0FH<br>AND AX,BX ;(AX)<--(AX) AND (BX)<br>AND DX,BUFFER[SI+BX]<br>AND BETA[BX],00FFH<br>注意: 两数相与,有一个数假则值为假| |CALL|过程调用指令 CALL<br>格式: CALL OPRD<br>功能: 过程调用指令|说明:<br>1. 其中OPRD为过程的目的地址.<br>2. 过程调用可分为段内调用和段间调用两种.寻址方式也可以分为直接寻址和间接寻址两种.<br>3. 本指令不影响标志位.| |CBW|字节扩展指令 CBW(Convert Byte to Word)<br>格式: CBW<br>功能: 将字节扩展为字,即把AL寄存器的符号位扩展到AH中.|说明:<br>1. 两个字节相除时,先使用本指令形成一个双字节长的被除数.<br>2. 本指令不影响标志位.<br>3. 示例: MOV AL,25<br>CBW<br>IDIV BYTE PTR DATA1| |CLC|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |CLD|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |CLI|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |CMC|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |CMP|比效指令 CMP(CoMPare)<br>格式: CMP OPRD1,OPRD2<br>功能: 对两数进行相减,进行比较.|说明:<br>1. OPRD1为任意通用寄存器或存储器操作数.<br>OPRD2为任意通用寄存器或存储器操作数,立即数也可用作源操作数OPRD2.<br>2. 对标志位的影响同SUB指令,完成的操作与SUB指令类似,唯一的区别是不将OPRD1-OPRD2的结果送回OPRD1,而只是比较.<br>3. 在8088/8086指令系统中,专门提供了一组根据带符号数比较大小后,实现条件转移的指令.| |CMPS|字符串比较指令<br>格式: CMPS OPRD1,OPRD2<br>CMPSB<br>CMPSW<br>功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身.<br>同时SI,DI将自动调整.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较.<br>3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.| |CMPSB|字符串比较指令<br>格式: CMPS OPRD1,OPRD2<br>CMPSB<br>CMPSW<br>功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身.<br>同时SI,DI将自动调整.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较.<br>3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.| |CMPSW|字符串比较指令<br>格式: CMPS OPRD1,OPRD2<br>CMPSB<br>CMPSW<br>功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身.<br>同时SI,DI将自动调整.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 本指令影响标志位AF、CF、OF、SF、PF、ZF.本指令可用来检查二个字符串是否相同,可以使用循环控制方法对整串进行比较.<br>3. 与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.| |CWD|字扩展指令 CWD(Convert Word to Double Word)<br>格式: CWD<br>功能: 将字扩展为双字长,即把AX寄存器的符号位扩展到DX中.|说明:<br>1. 两个字或字节相除时,先用本指令形成一个双字长的的被除数.<br>2. 本指令不影响标志位.<br>3. 示例: 在B1、B2、B3字节类型变量中,分别存有8们带符号数a、b、c,实现(a*b+c)/a运算。| |DAA|组合的十进制加法调整指令 DAA(Decimal Adjust for Addition)<br>格式: DAA<br>功能: 对AL中的两个组合进制数相加的结果进行调整,调整结果仍放在AL中,进位标志放在CF中.|说明:<br>1. 调整操作如下<br>(1) 若(AL) and 0FH>9 或 AF=1,则(AL)<--(AL)+6,AF<--1,对低四位的调整.<br>(2) 若(AL) and 0F0H>90H 或 CF=1,则(AL)<--(AL)+60H,CF<--1.<br>2. 示例: (AL)=18H,(BL)=06H<br>ADD AL,BL ; (AL)<--(AL)+(BL) ; (AL)=1EH<br>DAA ; (AL)| |DAS|组合十进制减法调整指令 DAS(Decimal Adjust for Subtraction)<br>格式: DAS<br>功能: 对两个组合十进制数相减后存于AL中的结果进行调整,调整后产生一个组合的十进制数且仍存于AL中.|说明:<br>调整操作<br>若(AL) and 0FH > 9 或 AF=1,则(AL)<--(AL)-6,AF=1<br>若(AL) and 0F0H > 90H 或 CF=1,则(AL)<--(AL)-60,CF=1| |DEC|减一指令 DEC(Decrement by 1)<br>格式: DEC OPRD<br>功能: OPRD<--OPRD-1|说明:<br>1. OPRD 为寄存器或存储器操作数.<br>2. 这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位.<br>3. 示例 DEC AX<br>DEC CL<br>DEC WORD PTR[DI]<br>DEC ALFA[DI+BX]| |DIV|无符号数除法指令 DIV(DIVision)<br>格式: DIV OPRD<br>功能: 实现两个无符号二进制数除法运算.|说明:<br>1. 其中OPRD为任一个通用寄存器或存储器操作数.<br>2. 字节相除,被除数在AX中;字相除,被除数在DX,AX中,除数在OPRD中.<br>字节除法: (AL)<--(AX)/OPRD,(AH)<--(AX)MOD OPRD<br>字除法: (AX)<--(DX)(AX)/OPRD,(DX)<--(DX)(AX) MOD OPRD| |ESC|处理器交权指令 ESC<br>格式: ESC EXTOPRD,OPRD<br>功能: 使用本指令可以实现协处理器出放在ESC指令代码中的6位常数,该常数指明协处理器要完成的功能.<br>当源操作数为存储器变量时,则取出该存储器操作数传送给协处理器.|说明:<br>1. 其中EXTOPRD为外部操作码,OPRD为源操作数.<br>2. 本指不影响标志位.| |HLT|处理器暂停指令 HLT<br>格式: HLT<br>功能: 使处理器处于暂时停机状态.|说明:<br>1. 本指令不影响标志位.<br>2. 由执行HLT引起的暂停,只有RESET(复位)、NMI(非屏蔽中断请求)、INTR(可屏蔽的外部中断请求)信号可以使<br>其退出暂停状态.它可用于等待中断的到来或多机系统的同步操作.| |IDIV|带符号数除法指定 IDIV(Interger DIVision)<br>格式: IDIV OPRD<br>功能: 这实现两个带符号数的二进制除法运算.|说明:<br>1. 其中OPRD为任一通用寄存器或存储器操作数.<br>2. 理由与IMUL相同,只有IDIV指令,才能得到符号数相除的正确结果.<br>3. 当被除数为8位,在进行字节除法前,应把AL的符号位扩充至AH中.在16位除法时,若被除数为16位,则应将AX中的符号位扩到DX中.| |IMUL|带符号数乘法指令 IMUL(Integer MULtiply)<br>格式: IMUL OPRD<br>功能: 完成两个带符号数的相乘|说明:<br>1. 其中OPRD为任一通用寄存器或存储器操作数.<br>2. MUL指令对带符号相乘时,不能得到正确的结果.<br>例如: (AL)=255<br>(CL)=255<br>MUL CL<br>(AX)=65025<br>注意: 这对无符号数讲,结果是正确的,但对带符号数讲,相当于(-1)*(-1)结果应为+1,而65025对应的带符号数为-511,显然是不正确的.| |IN|输入指令 IN<br>格式: IN AL,n ;(AL)<--(n)<br>IN AX,n ;(AX)<--(n+1),(n)<br>IN AL,DX ;(AL)<--[(DX)]<br>IN AX,DX ;(AX)<--[(DX)+1],[(DX)]<br>功能: 输入指令|说明:<br>1. 其中n为8位的端口地址,当字节输入时,将端口地址n+1的内容送至AH中,端口地址n的内容送AL中.<br>2. 端口地址也可以是16位的,但必须将16位的端口地址送入DX中.当字节寻址时,由DX内容作端口地址的内容送至AL中;<br>当输入数据字时,[(DX)+1]送AH,[(DX)]送AL中,用符号:(AX)<--[(DX)+1],[(DX)]表示.| |INC|加1指令 INC(INCrement by 1)<br>格式: INC OPRD<br>功能: OPRD<--OPRD+1|说明:<br>1. OPRD 为寄存器或存储器操作数.<br>2. 这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位.<br>3. 示例:<br>INC SI;(SI)<--(SI)+1<br>INC WORD PTR[BX]<br>INC BYTE PTR[BX+DI]<br>INC CL;(CL)<--(CL)+1<br>注意: 上述第二,三两条指令,是对存储字及存储字节的内容加1以替代原来的内容.| |INT|软中断指令 INT<br>格式: INT n 其中n为软中断的类型号.<br>功能: 本指令将产生一个软中断,把控制转向一个类型号为n的软中断,该中断处理程序入口地址在中断向量表的n*4地址<br>处的二个存储器字(4个单元)中.|说明: 操作过程与INTO指令雷同,只需将10H改为n*4即可.所以,本指令也将影响标志位IF及TF.| |INTO|溢出中断指令 INTO(INTerrupt if Overflow)<br>格式: INTO<br>功能: 本指令检测OF标志位,当OF=1时,说明已发生溢出,立即产生一个中断类型4的中断,当OF=0时,本指令不起作用.|说明:<br>1. 本指令影响标志位IF及TF.<br>2. 本指令可用于溢出处理,当OF=1时,产生一个类型4的软中断.在中断处理程序中完成溢出的处理操作.| |IRET|中断返回指令 IRET<br>格式: IRET<br>功能: 用于中断处理程序中,从中断程序的断点处返回,继续执行原程序.|说明:<br>1. 本指令将影响所有标志位.<br>2. 无论是软中断,还是硬中断,本指令均可使其返回到中断程序的断点处继续执行原程序.| |JA|条件转移指令JA/JNBE<br>格式: JA/JNBE标号<br>功能: 为高于/不低于等于的转移指令|说明:<br>1. 例如两个符号数a,b比较时,a>b(即CF=0,ZF=0)时转移.因为单一标志位CF=0,只表示a>=b.<br>2. JA/JNBE是同一条指令的两种不同的助记符.<br>3. 该指令用于无符号数进行条件转移| |JAE|条件转移指令JAE/JNB<br>格式: JAE/JNB 标号<br>功能: 为高于等于/不低于的转移指令|说明:<br>1. JAE/JNB是同一条指令的两种不同的助记符.<br>2. 该指令用于无符号数进行条件转移.| |JB|条件转移指令JB/JNAE<br>格式: JB/JNAE 标号<br>功能: 低于/不高于等于时转移|说明: 该指令用于无符号数的条件转移| |JBE|条件转移指令JBE/JNA<br>格式: JBE/JNA 标号<br>功能: 低于等于/不高于时转移|说明: 该指令用于无符号数的条件转移| |JC|条件转移指令 JC<br>格式: JC 标号<br>功能: CF=1,转至标号处执行|说明: JC为根据标志位CF进行转移的指令| |JE|条件转移指令JE/JZ<br>格式: JE/JZ标号<br>功能: ZF=1,转至标号处执|说明:<br>1. 指令JE与JZ等价,它们是根据标志位ZF进行转移的指令<br>2. JE,JZ均为一条指令的两种助记符表示方法| |JG|条件转移指令JG/JNLE<br>格式: JG/JNLE 标号<br>功能: 大于/不小于等于时转移|说明: 用于带符号数的条件转移指令| |JGE|条件转移指令JGE/JNL<br>格式: JGE/JNL标号<br>功能: 大于等于/不小于时转移|说明: 用于带符号数的条件转移指令| |JL|条件转移指令JL/JNGE<br>格式: JL/JNGE标号<br>功能: 小于/不大于等于时转移|说明: 用于带符号数的条件转移指令| |JLE|条件转移指令JLE/JNG<br>格式: JLE/JNG 标号<br>功能: 小于等于/不大于时转移|说明: 用于带符号数的条件转移指令| |JMP|无条件转移指令JMP<br>格式: JMP OPRD<br>功能: JMP指令将无条件地控制程序转移到目的地址去执行.当目的地址仍在同一个代码段内,称为段内转移;当目标地址不在同一个代码段内,则称为段间转移.这两种情况都将产生不同的指令代码,以便能正确地生成目的地址,在段内转移时,指令只要能提供目的地址的段内偏移量即够了;而在段间转移时,指令应能提供目的地址的段地址及段内偏移地址值.|说明:<br>1. 其中OPRD为转移的目的地址.程序转移到目的地址所指向的指令继续往下执行.<br>2. 本组指令对标志位无影响.<br>3. <1> 段内直接转移指令: JMP NEAR 标号<br><2> 段内间接转移指令: JMP OPRD<br><3> 段间直接转移指令: JMP FAR 标号<br><4> 段间间接转移指令:JMP OPRD其中的OPRD为存储器双字操作数.段间间接转移只能通过存储器操作数来实现.| |JNA|条件转移指令JBE/JNA<br>格式: JBE/JNA 标号<br>功能: 低于等于/不高于时转移|说明: 该指令用于无符号数的条件转移| |JNAE|条件转移指令JB/JNAE<br>格式: JB/JNAE 标号<br>功能: 低于/不高于等于时转移|说明: 该指令用于无符号数的条件转移| |JNB|条件转移指令JAE/JNB<br>格式: JAE/JNB 标号<br>功能: 为高于等于/不低于的转移指令|说明:<br>1. JAE/JNB是同一条指令的两种不同的助记符.<br>2. 该指令用于无符号数进行条件转移.| |JNBE|条件转移指令JA/JNBE<br>格式: JA/JNBE标号<br>功能: 为高于/不低于等于的转移指令|说明:<br>1. 例如两个符号数a,b比较时,a>b(即CF=0,ZF=0)时转移.因为单一标志位CF=0,只表示a>=b.<br>2. JA/JNBE是同一条指令的两种不同的助记符.<br>3. 该指令用于无符号数进行条件转移| |JNC|条件转移指令JNC<br>格式: JNC标号<br>功能: CF=0,转至标号处执行|说明: JNC为根据标志位CF进行转移的指令| |JNE|条件转移指令JNE/JNZ<br>格式: JNE/JNZ 标号<br>功能: ZF=0,转至标号处执行|说明:<br>1. 指令JNE与JNZ等价,它们是根据标志位ZF进行转移的指令<br>2. JNE,JNZ均为一条指令的两种助记符表示方法| |JNG|条件转移指令JLE/JNG<br>格式: JLE/JNG 标号<br>功能: 小于等于/不大于时转移|说明: 用于带符号数的条件转移指令| |JNGE|条件转移指令JL/JNGE<br>格式: JL/JNGE标号<br>功能: 小于/不大于等于时转移|说明: 用于带符号数的条件转移指令| |JNL|条件转移指令JGE/JNL<br>格式: JGE/JNL标号<br>功能: 大于等于/不小于时转移|说明: 用于带符号数的条件转移指令| |JNLE|条件转移指令JG/JNLE<br>格式: JG/JNLE 标号<br>功能: 大于/不小于等于时转移|说明: 用于带符号数的条件转移指令| |JNO|条件转移指令JNO<br>格式: JNO 标号<br>功能: OF=0,转至标号处执行|说明: JNO是根椐溢出标志位OF进行转移的指令| |JNP|条件转移指令JNP/JPO<br>格式: JNP/JPO 标号<br>功能: PF=0,转至标号处执行|说明:<br>1. 指令JNP与JPO,它们是根据奇偶标志位PF进行转移的指令<br>2. JNP,JPO均为一条指令的两种助记符表示方法| |JNS|条件转移指令JNS<br>格式: JNS 标号<br>功能: SF=0,转至标号处执行|说明: JNS是根据符号标志位SF进行转移的指令| |JNZ|条件转移指令JNE/JNZ<br>格式: JNE/JNZ 标号<br>功能: ZF=0,转至标号处执行|说明:<br>1. 指令JNE与JNZ等价,它们是根据标志位ZF进行转移的指令<br>2. JNE,JNZ均为一条指令的两种助记符表示方法| |JO|条件转移指令JO<br>格式: JO 标号<br>功能: OF=1,转至标号处执行|说明: JO是根椐溢出标志位OF进行转移的指令| |JP|条件转移指令JP/JPE<br>格式: JP/JPE 标号<br>功能: PF=1,转至标号处执行|说明:<br>1. 指令JP与JPE,它们是根据奇偶标志位PF进行转移的指令<br>2. JP,JPE均为一条指令的两种助记符表示方法| |JPE|条件转移指令JP/JPE<br>格式: JP/JPE 标号<br>功能: PF=1,转至标号处执行|说明:<br>1. 指令JP与JPE,它们是根据奇偶标志位PF进行转移的指令<br>2. JP,JPE均为一条指令的两种助记符表示方法| |JPO|条件转移指令JNP/JPO<br>格式: JNP/JPO 标号<br>功能: PF=0,转至标号处执行|说明:<br>1. 指令JNP与JPO,它们是根据奇偶标志位PF进行转移的指令<br>2. JNP,JPO均为一条指令的两种助记符表示方法| |JS|条件转移指令JS<br>格式: JS 标号<br>功能: SF=1,转至标号处执行|说明: JS是根据符号标志位SF进行转移的指令| |JZ|条件转移指令JE/JZ<br>格式: JE/JZ标号<br>功能: ZF=1,转至标号处执|说明:<br>1. 指令JE与JZ等价,它们是根据标志位ZF进行转移的指令<br>2. JE,JZ均为一条指令的两种助记符表示方法| |LAHF|标志传送指令 LAHF<br>格式: LAHF<br>功能: 取FLAG标志寄存器低8位至AH寄存器.(AH)<--(FLAG)7~0|说明: 该指令不影响FLAG的原来内容,AH只是复制了原FLAG的低8位内容.| |LDS|从存储器取出32位地址的指令 LDS<br>格式: LDS OPRD1,OPRD2<br>功能: 从存储器取出32位地址的指令.|说明:<br>OPRD1 为任意一个16位的寄存器.<br>OPRD2 为32位的存储器地址.<br>示例: LDS SI,ABCD<br>LDS BX,FAST[SI]<br>LDS DI,[BX]<br>注意: 上面LDS DI,[BX]指令的功能是把BX所指的32位地址指针的段地址送入DS,偏移地址送入DI.| |LEA|有效地址传送指令 LEA<br>格式: LEA OPRD1,OPRD2<br>功能: 将源操作数给出的有效地址传送到指定的的寄存器中.|说明:<br>1. OPRD1 为目的操作数,可为任意一个16位的通用寄存器.<br>OPRD2 为源操作数,可为变量名、标号或地址表达式.<br>示例: LEA BX,DATA1<br>LEA DX,BETA[BX+SI]<br>LEA BX BX,[BP],[DI]<br>2. 本指令对标志位无影响。| |LES|从存储器取出32位地址的指令 LES<br>格式: LES OPRD1,OPRD2<br>功能: 从存储器取出32位地址的指令.|说明:<br>OPRD1 为任意一个16位的寄存器.<br>OPRD2 为32位的存储器地址.<br>示例: LES SI,ABCD<br>LES BX,FAST[SI]<br>LES DI,[BX]<br>注意: 上面LES DI,[BX]指令的功能是把BX所指的32位地址指针的段地址送入ES,偏移地址送入DI.| |LOCK|封锁总线指令 LOCK<br>格式: LOCK<br>功能: 指令是一个前缀,可放在指令的前面,告诉CPU在执行该指令时,不允许其它设备对总线进行访问.|无可用信息!用户可自行添加!| |LODS|取字符串元素指令 LODS<br>格式: LODS OPRD 其中OPRD为源字符串符号地址.<br>功能: 把SI寻址的源串的数据字节送AL或数据字送AX中去, 并根据DF的值修改地址指针SI进行自动调整.|说明:<br>1. 本指令不影响标志位.<br>2. 当不使用操作数时,可用LODS(字节串)或LODSW(字串)指令.| |LOOP|循环控制指令LOOP<br>格式: LOOP 标号<br>功能: (CX)<--(CX)-1,(CX)<>0,则转移至标号处循环执行, 直至(CX)=0,继续执行后继指令.|说明:<br>1. 本指令是用CX寄存器作为计数器,来控制程序的循环.<br>2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.| |LOOPE|循环控制指令LOOPZ/LOOPE<br>格式: LOOPZ/LOOPE 标号<br>功能: (CX)<--(CX)-1,(CX)<>0 且ZF=1时,转至标号处循环|说明:<br>1. 本指令是用CX寄存器作为计数器,来控制程序的循环.<br>2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.<br>3. 以上两种助记符等价.| |LOOPNE|循环控制指令LOOPNZ/LOOPNE<br>格式: LOOPNZ/LOOPNE 标号<br>功能: (CX)<--(CX)-1,(CX)<>0 且ZF=0时,转至标号处循环|说明:<br>1. 本指令是用CX寄存器作为计数器,来控制程序的循环.<br>2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.<br>3. 以上两种助记符等价.| |LOOPNZ|循环控制指令LOOPNZ/LOOPNE<br>格式: LOOPNZ/LOOPNE 标号<br>功能: (CX)<--(CX)-1,(CX)<>0 且ZF=0时,转至标号处循环|说明:<br>1. 本指令是用CX寄存器作为计数器,来控制程序的循环.<br>2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.<br>3. 以上两种助记符等价.| |LOOPZ|循环控制指令LOOPZ/LOOPE<br>格式: LOOPZ/LOOPE 标号<br>功能: (CX)<--(CX)-1,(CX)<>0 且ZF=1时,转至标号处循环|说明:<br>1. 本指令是用CX寄存器作为计数器,来控制程序的循环.<br>2. 它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.<br>3. 以上两种助记符等价.| |MOVE|数据传送指令 MOV<br>格式: MOV OPRD1,OPRD2<br>功能: 本指令将一个源操作数送到目的操作数中,即OPRD1<--OPRD2.|说明:<br>1. OPRD1 为目的操作数,可以是寄存器、存储器、累加器.<br>OPRD2 为源操作数,可以是寄存器、存储器、累加器和立即数.<br>2. MOV 指令以分为以下四种情况:<br><1> 寄存器与寄存器之间的数据传送指令<br><2> 立即数到通用寄存器数据传送指令<br><3> 寄存器与存储器之间的数据传送指令<br><4> 立即数到存储器的数据传送<br>3. 本指令不影响状态标志位| |MOVS|字符串传送指令 MOVS<br>格式: MOVS OPRD1,OPRD2<br>MOVSB<br>MOVSW<br>功能: OPRD1<--OPRD2.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减.<br>3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,.<br>4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW.<br>5. 本指令不影响标志位.| |MOVSB|字符串传送指令 MOVS<br>格式: MOVS OPRD1,OPRD2<br>MOVSB<br>MOVSW<br>功能: OPRD1<--OPRD2.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减.<br>3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,.<br>4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW.<br>5. 本指令不影响标志位.| |MOVSW|字符串传送指令 MOVS<br>格式: MOVS OPRD1,OPRD2<br>MOVSB<br>MOVSW<br>功能: OPRD1<--OPRD2.|说明:<br>1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址.<br>2. 字节串操作: 若DF=0,则作加, 若DF=1,则作减.<br>3. 对字串操作时: 若DF=0,则作加,若DF=1,则作减,.<br>4. 在指令中不出现操作数时,字节串传送格式为MOVSB、字串传送格式为MOVSW.<br>5. 本指令不影响标志位.| |MUL|无符号数乘法指令 MUL(MULtiply)<br>格式: MUL OPRD<br>功能: 乘法操作.|说明:<br>1. OPRD为通用寄存器或存储器操作数.<br>2. OPRD为源操作数,即作乘数.目的操作数是隐含的,即被乘数总是指定为累加器AX或AL的内容.<br>3. 16位乘法时,AX中为被乘数.8位乘法时,AL为被乘数.当16位乘法时,32位的乘积存于DX及AX中;8位乘法的16位乘积存于AX中.<br>4. 操作过程: 字节相乘:(AX)<--(AL)*OPRD,当结果的高位字节(AH)不等于0时,则CF=1、OF=1.| |NEG|取补指令 NEG(NEGate)<br>格式: NEG OPRD<br>功能: 对操作数OPRD进行取补操作,然后将结果送回OPRD.取补操作也叫作求补操作,就是求一个数的相反数的补码.|说明:<br>1. OPRD为任意通用寄存器或存储器操作数.<br>2. 示例: (AL)=44H,取补后,(AL)=0BCH(-44H).<br>3. 本指令影响标志位CF、OF、SF、PF、ZF及AF.| |NOP|空操作指令 NOP<br>格式: NOP<br>功能: 本指令不产生任何结果,仅消耗几个时钟周期的时间,接着执行后续指令,常用于程序的延时等.|说明: 本指令不影响标志位.| |NOT|逻辑非运算指令 NOT<br>格式: NOT OPRD<br>功能: 完成对操作数按位求反运算(即0变1,1变0),结果关回原操作数.|说明:<br>1. 其中OPRD可为任一通用寄存器或存储器操作数.<br>2. 本指梳令可以进行字或字节‘非’运算.<br>3. 本指令不影响标志位.| |OR|逻辑或指令 OR<br>格式: OR OPRD1,OPRD2<br>功能: OR指令完成对两个操作数按位的‘或’运算,结果送至目的操作数中,本指令可以进行字节或字的‘或’运算.<br>OPRD1<--OPRD1 OR OPRD2.|说明:<br>1. 其中OPRD1,OPRD2含义与AND指令相同,对标志位的影响也与AND指令相同.<br>2. 两数相或,有一个数为真则值为真.| |OUT|输出指令 OUT<br>格式: OUT n,AL ;(n)<--(AL)<br>功能: 输出指令|说明:<br>1. OUT n,AX ;(n+1),(n)<--(AX)<br>OUT DX,AL ;[(DX)]<--(AL)<br>OUT DX,AX ;[(DX)+1],[(DX)]<--(AX)<br>2. 输入指令及输出指令对标志位都不影响.| |POP|堆栈操作指令 PUSH和POP<br>格式: PUSH OPRD<br>POP OPRD<br>功能: 实现压入操作的指令是PUSH指令;实现弹出操作的指令是POP指令.|说明:<br>1. OPRD为16位(字)操作数,可以是寄存器或存储器操作数.<br>2. POP指令的操作过程是: POP OPRD:OPRD<--((SP)),(SP)<--(SP)+2<br>它与压入操作相反,是先弹出栈顶的数顶,然后再修改指针SP的内容.<br>3. 示例: POP AX<br>POP DS<br>POP DATA1 POP ALFA[BX][DI]<br>4. PUSH和POP指令对状态标志位没有影响.| |POPF|标志传送指令 POPF<br>格式: POPF<br>功能: 本指令的功能与PUSHF相反,在子程序调用和中断服务程序中,往往用PUSHF指令保护FLAG的内容,用POPF指令将保护的FLAG内容恢复.|说明: 如果对堆栈中的原FLAG内容进行修改,如对TF等标志位进行修改,然后再弹回标志位寄存器FLAG.这是通过指令修改TF标志的唯一方法.| |PUSH|堆栈操作指令 PUSH和POP<br>格式: PUSH OPRD<br>POP OPRD<br>功能: 实现压入操作的指令是PUSH指令;实现弹出操作的指令是POP指令.|说明:<br>1. OPRD为16位(字)操作数,可以是寄存器或存储器操作数.<br>2. PUSH的操作过程是: (SP)<--(SP)-2,((sp))<--OPRD 即先修改堆栈指针SP(压入时为自动减2),然后,将指定的操作数送入新的栈顶位置.<br>此处的((SP))<--OPRD,也可以理解为: [(SS)*16+(SP)]<--OPRD 或 [SS:SP]<--OPRD| |PUSHF|标志传送指令 PUSHF<br>格式: PUSHF<br>功能: 本指令可以把标志寄存器的内容保存到堆栈中去| | |RCL|循环移位指令<br>格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令.<br>ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令.<br>RCL OPRD1,COUNT ;带进位的左循环移位指令.<br>RCR OPRD1,COUNT ;带进位的右循环移位指令.|说明:<br>1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1.<br>2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入,<br>所以可以利用它实现多字节的循环.| |RCR|循环移位指令<br>格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令.<br>ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令.<br>RCL OPRD1,COUNT ;带进位的左循环移位指令.<br>RCR OPRD1,COUNT ;带进位的右循环移位指令.|说明:<br>1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1.<br>2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入,所以可以利用它实现多字节的循环.<br>注意: 以上程序中的指令SHR AL,CL如改为SAR AL,CL,虽然最高4位可移入低4位,但最高位不为0,故应加入一条指令AND AL,0FH.否则,若最高位不为0时,将得到错误结果.| |REP|重复前缀的说明<br>格式: REP ;CX<>0 重复执行字符串指令<br>REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令<br>REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令<br>功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中.|说明:<br>1. REP与MOVS或STOS串操作指令相结合使用,完成一组字符的传送或建立一组相同数据的字符串.<br>2. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较.<br>3. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字.<br>4. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.| |REPE|重复前缀的说明<br>格式: REP ;CX<>0 重复执行字符串指令<br>REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令<br>REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令<br>功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中.|说明:<br>1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较.<br>2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字.<br>3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.<br>4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.| |REPNE|重复前缀的说明<br>格式: REP ;CX<>0 重复执行字符串指令<br>REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令<br>REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令|说明:<br>1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较.<br>2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字.<br>3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.<br>4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.| |REPNZ|重复前缀的说明<br>格式: REP ;CX<>0 重复执行字符串指令<br>REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令<br>REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令|说明:<br>1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较.<br>2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字.<br>3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.<br>4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.| |REPZ|重复前缀的说明<br>格式: REP ;CX<>0 重复执行字符串指令<br>REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令<br>REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令<br>功能: 在串操作指令前加上重复前缀,可以对字符串进重复处理.由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中.|说明:<br>1. REPZ/REPE常用与CMPS串操作指令结合使用, 可以完成两组字符串的比较.<br>2. REPZ/REPE常与SCAS指令结合使用,可以完成在一个字符串中搜索一个关键字.<br>3. REPNZ/REPNE与CMPS指令结合使用,表示当串未结束(CX=1)且当对应串元素不相同(ZF=0)时,继续重复执行串比较指令.<br>4. REPNZ/REPNE与SCAS指令结合使用,表示串未结束(CX=1)且当关键字与串元素不相同(ZF=0)时,继续重复执行串搜索指令.| |RET|返回指令 RET<br>格式: RET<br>功能: 当调用的过程结束后实现从过程返回至原调用程序的下一条指令,本指令不影响标志位.|说明:<br>由于在过程定义时,已指明其近(NEAR)或远(FAR)的属性,所以RET指令根据段内调用与段间调用,执行不同的操作<br>对段内调用: 返回时,由堆栈弹出一个字的返回地址的段内偏移量至IP.<br>对段外调用: 返回时,由堆栈弹出的第一个字为返回地址的段内偏移量,将其送入IP中,由堆栈弹出第二个字为返回地址的段基址,将其送入CS中.| |ROL|循环移位指令<br>格式: ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令.<br>ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令.<br>RCL OPRD1,COUNT ;带进位的左循环移位指令.<br>RCR OPRD1,COUNT ;带进位的右循环移位指令.|说明:<br>1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1.<br>2. 由于是循环移位,所以对字节移位8次; 对字移位16次,就可恢复为原操作数.由于带CF的循环移位,可以将CF的内容移入,<br>所以可以利用它实现多字节的循环.| |ROR|循环移位指令<br>格式:<br>ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令.<br>ROR OPRD1,COUNT ;不含进位示志位CF在循环中的右循环移位指令.<br>RCL OPRD1,COUNT ;带进位的左循环移位指令.<br>RCR OPRD1,COUNT ;带进位的右循环移位指令.|说明:<br>1. 本指令组只影响标志CF、OF.OF由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变,则OF=1.<br>2. 由于循环移位,所以对字节移位8次; 对字移位16次,可恢复为原操作数.| |SAHF|标志传送指令 SAHF<br>格式: SAHF<br>功能: 将AH存至FLAG低8位|说明: 本指令将用AH的内容改写FLAG标志寄存器中的SF、ZF、AF、PF、和CF标志,从而改变原来的标志位.| |SAL|算术左移指令 SAL(Shift Arithmetic Left)<br>格式: SAL OPRD1,COUNT<br>功能: 其中OPRD1,COUNT与指令SHL相同.本指令与SHL的功能也完全相同,这是因为逻辑左移指令与算术左移指令所要完成的操作是一样的.|说明:<br>1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数.<br>2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.| |SAR|算术右移指令 SAR<br>格式: SAR OPRD1,COUNT<br>功能: 本指令通常用于对带符号数减半的运算中,因而在每次右移时,保持最高位(符号位)不变,最低位右移至CF中.|说明:<br>1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数.<br>2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.| |SBB|带借位减去指令 SBB(SuBtraction with Borrow)<br>格式: SBB OPRD1,OPRD2<br>功能: 是进行两个操作数的相减再减去CF进位标志位,即从OPRD1<--OPRD1-OPRD2-CF,其结果放在OPDR1中.|说明:<br>示例 SBB DX,CX<br>SBB AX,DATA1<br>SBB BX,2000H<br>SBB ALFA[BX+SI],SI<br>SBB BETAP[DI,030AH| |SCAS|字符串搜索指令 SCAS<br>格式: SCAS OPRD<br>SCASB<br>SCASW<br>功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身.<br>地址指针DI自动调整.|说明:<br>1. 其中OPRD为目的串符号地址.<br>2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前,<br>把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找.<br>指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.| |SCASB|字符串搜索指令 SCAS<br>格式: SCAS OPRD<br>SCASB<br>SCASW<br>功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身.<br>地址指针DI自动调整.|说明:<br>1. 其中OPRD为目的串符号地址.<br>2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前,<br>把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找.<br>指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.| |SCASW|字符串搜索指令 SCAS<br>格式: SCAS OPRD<br>SCASB<br>SCASW<br>功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身.<br>地址指针DI自动调整.|说明:<br>1. 其中OPRD为目的串符号地址.<br>2. 本指令影响标志AF、CF、OF、PF、SF、ZF.该指令可查找字符串中的一个关键字,只需在本指令执行前,<br>把关键字放在AL(字节)或AX(字串 )中,用重复前缀可在整串中查找.<br>指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.| |SHL|逻辑左移指令 SHL(Shift logical left)<br>格式: SHL OPRD1,COUNT<br>功能: 对给定的目的操作数左移COUNT次,每次移位时最高位移入标志位CF中,最低位补零.|说明:<br>1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数.<br>2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.<br>3. 例如: SHL AL,1<br>SHL CX,1<br>SHL ALFA[DI] 或者:<br>MOV CL,3<br>SHL DX,CL<br>SHL ALFA[DI],CL| |SHR|逻辑右移指令 SHR<br>格式: SHR OPRD1,COUNT<br>功能: 本指令实现由COUNT决定次数的逻辑右移操作,每次移位时,最高位补0,最低位移至标志位CF中.|说明:<br>1. 其中OPRD1为目的操作数,可以是通用寄存器或存储器操作数.<br>2. COUNT代表移位的次数(或位数).移位一次,COUNT=1;移位多于1次时,COUNT=(CL),(CL)中为移位的次数.<br>3. 影响标志位OF,PF,SF,ZF,CF.| |STC|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |STD|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |STI|处理器控制指令-标志位操作指令<br>格式:<br>CLC ;置CF=0<br>STC ;置CF=1<br>CMC ;置CF=(Not CF)进位标志求反<br>CLD ;置DF=0<br>STD ;置DF=1<br>CLI ;置IF=0,CPU禁止响应外部中断<br>STI ;置IF=1,使CPU允许向应外部中断<br>功能: 完成对标志位的置位、复位等操作.|说明: 例如串操作中的程序,经常用CLD指令清方向标志使DF=0,在串操作指令执行时,按增量的方式修改吕指针.| |STOS|字符串存储指令 STOS<br>格式: STOS OPRD<br>功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去.指针DI将根据DF的值进行自动调整.|说明:<br>1. 其中OPRD为目的串符号地址.<br>2. 本指令不影响标志位.当不使用操作数时,可用STOSB或STOSW分别表示字节串或字串的操作.| |SUB|减法指令SUB(SUBtract)<br>格式: SUB OPRD1,OPRD2<br>功能: 两个操作数的相减,即从OPRD1中减去OPRD2,其结果放在OPDR1中.|说明:<br>示例 SUB DX,CX<br>SUB [BX+25],AX<br>SUB DI,ALFA[SI]<br>SUB CL,20<br>SUB DATA1[DI][BX],20A5H| |TEST|测试指令 TEST<br>格式: TEST OPRD1,OPRD2<br>功能: 其中OPRD1、OPRD2的含义同AND指令一样,也是对两个操作数进行按位的'与'运算,唯一不同之处是不将'与'的结<br>果送目的操作数,即本指令对两个操作数 的内容均不进行修改,仅是在逻辑与操作后,对标志位重新置位.|说明: TEST与AND指令的关系,有点类似于CMP与SUB指令之间的关系.| |WAIT|处理器等待指令 WAIT<br>格式: WAIT<br>功能: 本指令将使处理器检测TEST端脚,当TEST有效时,则退出等待状态执行下条指令,否则处理器处于等待状态,直到TEST有效.|说明: 本指令不影响标志位.| |XCHG|数据交换指令 XCHG<br>格式: XCHG OPRD1,OPRD2 其中的OPRD1为目的操作数,OPRD2为源操作数<br>功能: 将两个操作数相互交换位置,该指令把源操作数OPRD2与目的操数OPRD1交换.|说明:<br>1. OPRD1及OPRD2可为通用寄存器或存储器,但是两个存储器之间是不能用XCHG指令实现的.<br>2. 段寄存器内容不能用XCHG指令来交换.<br>3. 若要实现两个存储器操作数DATA1及DATA2的交换,可用以下指令实现:<br>示例: PUSH DATA1<br>PUSH DATA2<br>POP DATA1<br>POP DATA2<br>4. 本指令不影响状态标志位.| |XLAT|查表指令 XLAT<br>格式: XLAT TABLE其中TABLE为一待查表格的首地址.<br>功能: 把待查表格的一个字节内容送到AL累加器中.|说明:<br>1. 在执行该指令前,应将TABLE先送至BX寄存器中,然后将待查字节与在表格中距表首地址位移量送AL,即 (AL)<--((BX)+(AL)).<br>2. 本指令不影响状态标位,表格长度不超过256字节.| |XOR|逻辑异或运算指令 XOR<br>格式: XOR OPRD1,OPRD2<br>功能: 实现两个操作数按位‘异或’运算,结果送至目的操作数中.<br>OPRD1<--OPRD1 XOR OPRD2|说明:<br>1. 其在OPRD1、OPRD2的含义与AND指令相同,对标志位的影响与与AND指令相同.<br>2. 相异为真,相同为假.| | 指令 | 功能 | | 指令 | 功能 | | 指令 | 功能 | | --- | --- | --- | --- | --- | --- | --- | --- | | AAA | 调整加 | | JA | 高于跳转 | | SAHF | 恢复标志低八 | | AAD | 调整除 | | JB | 低于跳转 | | SAL | 算术左移 | | AAM | 调整乘 | | JBE | 不高于跳转 | | SALC | | | AAS | 调整减 | | JCXZ | 计数一六零跳转 | | SAR | 算术右移 | | ADC | 进位加 | | JE | 相等跳转 | | SBB | 借位减 | | ADD | 加 | | JECXZ | 计数三二零跳转 | | SCASB | 扫描字节串 | | AND | 与 | | JG | 大于跳转 | | SCASD | 扫描双字串 | | ARPL | 调整优先级 | | JL | 小于跳转 | | SCASW | 扫描字串 | | | | | JMP | 跳转 | | SETA | 高于置位 | | BOUND | 检查数组 | | JMPE | 跳转扩展 | | SETB | 低于置位 | | BSF | 位右扫描 | | JNB | 不低于跳转 | | SETE | 相等置位 | | BSR | 位左扫描 | | JNE | 不等跳转 | | SETG | 大于置位 | | BSWAP | 交换字节 | | JNG | 不大于跳转 | | SETL | 小于置位 | | BT | 位测试 | | JNL | 不小于跳转 | | SETNA | 不高于置位 | | BTC | 位测试求反 | | JNO | 不溢出跳转 | | SETNB | 不低于置位 | | BTR | 位测试清零 | | JNP | 非奇偶跳转 | | SETNE | 不等置位 | | BTS | 位测试置一 | | JNS | 非负跳转 | | SETNG | 不大于置位 | | | | | JO | 溢出跳转 | | SETNL | 不小于置位 | | CALL | 过程调用 | | JP | 奇偶跳转 | | SETNO | 不溢出置位 | | CBW | 转换字节 | | JS | 负号跳转 | | SETNP | 非奇偶置位 | | CDQ | 转换双字 | | LAHF | 加载标志低八 | | SETNS | 非负置位 | | CLC | 进位清零 | | LAR | 加载访问权限 | | SETO | 溢出置位 | | CLD | 方向清零 | | LDS | 加载数据段 | | SETP | 奇偶置位 | | CLI | 中断清零 | | LEA | 加载有效地址 | | SETS | 负号置位 | | CLTS | 任务清除 | | LEAVE | 清除过程堆栈 | | SGDT | 保存全局描述符 | | CMC | 进位求反 | | LES | 加载附加段 | | SHL | 逻辑左移 | | CMOVA | 高于传送 | | LFS | 加载标志段 | | SHLD | 双精度左移 | | CMOVB | 低于传送 | | LGDT | 加载全局描述符 | | SHR | 逻辑右移 | | CMOVE | 相等传送 | | LGS | 加载全局段 | | SHRD | 双精度右移 | | CMOVG | 大于传送 | | LIDT | 加载中断描述符 | | SIDT | 保存中断描述符 | | CMOVL | 小于传送 | | LMSW | 加载状态字 | | SLDT | 保存局部描述符 | | CMOVNA | 不高于传送 | | LOADALL | 加载所有 | | SMI | | | CMOVNB | 不低于传送 | | LOADALL286 | 加载所有286 | | SMINT | | | CMOVNE | 不等传送 | | LOCK | 锁 | | SMINTOLD | | | CMOVNG | 不大于传送 | | LODSB | 加载源变址字节串 | | SMSW | 保存状态字 | | CMOVNL | 不小于传送 | | LODSD | 加载源变址双字串 | | STC | 进位设置 | | CMOVNO | 不溢出传送 | | LODSW | 加载源变址字串 | | STD | 方向设置 | | CMOVNP | 非奇偶传送 | | LOOP | 计数循环 | | STI | 中断设置 | | CMOVNS | 非负传送 | | LOOPE | 相等循环 | | STOSB | 保存字节串 | | CMOVO | 溢出传送 | | LOOPNE | 不等循环 | | STOSD | 保存双字串 | | CMOVP | 奇偶传送 | | LOOPNZ | 非零循环 | | STOSW | 保存字串 | | CMOVS | 负号传送 | | LOOPZ | 为零循环 | | STR | 保存任务 | | CMP | 比较 | | LSL | 加载段界限 | | SUB | 减 | | CMPSB | 比较字节串 | | LSS | 加载堆栈段 | | SYSCALL | 系统调用 | | CMPSD | 比较双字串 | | LTR | 加载任务 | | SYSENTER | 系统进入 | | CMPSW | 比较字串 | | MONITOR | 监视 | | SYSEXIT | 系统退出 | | CMPXCHG | 比较交换 | | MOV | 传送 | | SYSRET | 系统返回 | | CMPXCHG486 | 比较交换486 | | MOVSB | 传送字节串 | | TEST | 数测试 | | CMPXCHG8B | 比较交换8字节 | | MOVSD | 传送双字串 | | UD0 | 未定义指令0 | | CPUID | CPU标识 | | MOVSW | 传送字串 | | UD1 | 未定义指令1 | | CWD | 转换字 | | MOVSX | 符号传送 | | UD2 | 未定义指令2 | | CWDE | 扩展字 | | MOVZX | 零传送 | | UMOV | | | | | | MUL | 乘 | | VERW | 校验写 | | DAA | 调整加十 | | MWAIT | | | WAIT | 等 | | DAS | 调整减十 | | NEG | 求补 | | WBINVD | 回写无效高速缓存 | | DEC | 减一 | | NOP | 空 | | WRMSR | 写专用模式 | | DIV | 除 | | NOT | 非 | | WRSHR | | | | | | OR | 或 | | XADD | 交换加 | | ENTER | 建立堆栈帧 | | OUT | 端口输出 | | XBTS | | | HLT | 停 | | OUTSB | 端口输出字节串 | | XCHG | 交换 | | IDIV | 符号整除 | | OUTSD | 端口输出双字串 | | XLAT | 换码 | | IMUL | 符号乘法 | | OUTSW | 端口输出字串 | | XOR | 异或 | | IN | 端口输入 | | POP | 出栈 | | XSTORE | | | INC | 加一 | | POPA | 全部出栈 | | | | | INSB | 端口输入字节串 | | POPF | 标志出栈 | | | | | INSD | 端口输入双字串 | | PUSH | 压栈 | | | | | INSW | 端口输入字串 | | PUSHA | 全部压栈 | | | | | | | | PUSHF | 标志压栈 | | | | | | | | RCL | 进位循环左移 | | | | | | | | RCR | 进位循环右移 | | | | | | | | RDMSR | 读专用模式 | | | | | | | | RDPMC | 读执行监视计数 | | | | | | | | RDSHR | | | | | | | | | RDTSC | 读时间戳计数 | | | | | | | | REP | 重复 | | | | | | | | REPE | 相等重复 | | | | | | | | REPNE | 不等重复 | | | | | | | | RET | 过程返回 | | | | | | | | RETF | 远过程返回 | | | | | | | | RETN | 近过程返回 | | | | | | | | ROL | 循环左移 | | | | | | | | ROR | 循环右移 | | | | | | | | RSM | 恢复系统管理 | | | | | 指令 | 功能 | | 指令 | 功能 | | 指令 | 功能 | | EMMS | 媒体空MMX状态 | | FMUL | 浮点乘 | | MOVED | 媒体双字传送 | | F2XM1 | 浮点栈顶绝对值 | | FMULP | 浮点乘出栈 | | MOVEQ | 媒体四字传送 | | FADD | 浮点加 | | FNCLEX | 浮点不检查错误清除 | | PACKSSDW | 媒体符号双字压缩 | | FADDP | 浮点加出栈 | | FNDISI | 浮点不检查禁止中断 | | PACKSSWB | 媒体符号字压缩 | | FBLD | 浮点加载十数 | | FNENI | 浮点不检查禁止中断二 | | PACKUSWB | 媒体无符号字压缩 | | FBSTP | 浮点保存十数出栈 | | FNINIT | 浮点不检查初始化 | | PADDB | 媒体截断字节加 | | FCHS | 浮点正负求反 | | FNOP | 浮点空 | | PADDD | 媒体截断双字加 | | FCLEX | 浮点检查错误清除 | | FNSAVE | 浮点不检查保存状态 | | PADDSB | 媒体符号饱和字节加 | | FCMOVB | 浮点低于传送 | | FNSTCW | 浮点不检查保存控制器 | | PADDSIW | | | FCMOVBE | 浮点不高于传送 | | FNSTENV | 浮点不检查保存环境 | | PADDSW | 媒体符号饱和字加 | | FCMOVE | 浮点相等传送 | | FNSTSW | 浮点不检查保存状态器 | | PADDUSB | 媒体无符号饱和字节加 | | FCMOVNB | 浮点不低于传送 | | FPATAN | 浮点部分反正切 | | PADDUSW | 媒体无符号饱和字加 | | FCMOVNBE | 浮点高于传送 | | FPREM | 浮点部分余数 | | PADDW | 媒体截断字加 | | FCMOVNE | 浮点不等传送 | | FPREM1 | 浮点部分余数二 | | PAND | 媒体与 | | FCMOVNU | 浮点有序传送 | | FPTAN | 浮点部分正切 | | PANDN | 媒体与非 | | FCMOVU | 浮点无序传送 | | FRNDINT | 浮点舍入求整 | | PAVEB | | | FCOM | 浮点比较 | | FRSTOR | 浮点恢复状态 | | PCMPEQB | 媒体字节比等 | | FCOMI | 浮点比较加载标志 | | FSAVE | 浮点检查保存状态 | | PCMPEQD | 媒体双字比等 | | FCOMIP | 浮点比较加载标志出栈 | | FSCALE | 浮点比例运算 | | PCMPEQW | 媒体字比等 | | FCOMP | 浮点比较出栈 | | FSETPM | 浮点设置保护 | | PCMPGTB | 媒体字节比大 | | FCOMPP | 浮点比较出栈二 | | FSIN | 浮点正弦 | | PCMPGTD | 媒体双字比大 | | FCOS | 浮点余弦 | | FSINCOS | 浮点正余弦 | | PCMPGTW | 媒体字比大 | | FDECSTP | 浮点栈针减一 | | FSQRT | 浮点平方根 | | PDISTIB | | | FDISI | 浮点检查禁止中断 | | FST | 浮点保存 | | PMACHRIW | | | FDIV | 浮点除 | | FSTCW | 浮点检查保存控制器 | | PMADDWD | | | FDIVP | 浮点除出栈 | | FSTENV | 浮点检查保存环境 | | PMAGW | | | FDIVR | 浮点反除 | | FSTP | 浮点保存出栈 | | PMULHRIW | | | FDIVRP | 浮点反除出栈 | | FSTSW | 浮点检查保存状态器 | | PMULHRWC | | | FENI | 浮点检查禁止中断二 | | FSUB | 浮点减 | | PMULHW | | | FFREE | 浮点释放 | | FSUBP | 浮点减出栈 | | PMVGEZB | | | FFREEP | 浮点释放出栈 | | FSUBR | 浮点反减 | | PMVLZB | | | FIADD | 浮点加整数 | | FSUBRP | 浮点反减出栈 | | PMVNZB | | | FICOM | 浮点比较整数 | | FTST | 浮点比零 | | PMVZB | | | FICOMP | 浮点比较整数出栈 | | FUCOM | 浮点无序比较 | | POR | 媒体或 | | FIDIV | 浮点除整数 | | FUCOMI | 浮点反比加载标志 | | PSLLD | 媒体双字左移 | | FIDIVR | 浮点反除 | | FUCOMIP | 浮点反比加载标志出栈 | | PSLLQ | 媒体四字左移 | | FILD | 浮点加载整数 | | FUCOMP | 浮点无序比较出栈 | | PSLLW | 媒体字左移 | | FIMUL | 浮点乘整数 | | FUCOMPP | 浮点无序比较出栈二 | | PSRAD | 媒体双字算术右移 | | FINCSTP | 浮点栈针加一 | | FWAIT | 浮点等 | | PSRAW | 媒体字算术右移 | | FINIT | 浮点检查初始化 | | FXAM | 浮点检查 | | PSRLD | 媒体双字右移 | | FIST | 浮点保存整数 | | FXCH | 浮点交换 | | PSRLQ | 媒体四字右移 | | FISTP | 浮点保存整数出栈 | | FXTRACT | 浮点分解 | | PSRLW | 媒体字右移 | | FISTTP | | | FYL2X | 浮点求L2X | | PSUBB | 媒体截断字节减 | | FISUB | 浮点减整数 | | FYL2XP1 | 浮点求L2XP1 | | PSUBSB | 媒体符号饱和字节减 | | FISUBR | 浮点反减整数 | | | | | PSUBSIW | | | FLD | 浮点加载数 | | | | | PSUBSW | 媒体符号饱和字减 | | FLD1 | 浮点加载一 | | | | | PSUBUSB | 媒体无符号饱和字节减 | | FLDCW | 浮点加载控制器 | | | | | PSUBUSW | 媒体无符号饱和字减 | | FLDENV | 浮点加载环境 | | | | | PSUBW | 媒体截断字减 | | FLDL2E | 浮点加载L2E | | | | | PUNPCKHBW | 媒体字节高位解压 | | FLDL2T | 浮点加载L2T | | | | | PUNPCKHDQ | 媒体双字高位解压 | | FLDLG2 | 浮点加载LG2 | | | | | PUNPCKHWD | 媒体字高位解压 | | FLDLN2 | 浮点加载LN2 | | | | | PUNPCKLBW | 媒体字节低位解压 | | FLDPI | 浮点加载PI | | | | | PUNPCKLDQ | 媒体双字低位解压 | | FLDZ | 浮点加载零 | | | | | PUNPCKLWD | 媒体字低位解压 |
CopyRight 2002~2023 精通2100网 联系邮箱:qqtxt@163.com
版权所有:精通2100网
湘ICP备2023018646号-1
MYSQl共执行 4 个查询,用时 0.0023462772369385 秒,PHP脚本用时 0.010586 秒,占用内存 1.381 MB,Gzip 已启用