「x86」- 指令集(学习笔记)

  CREATED BY JENKINSBOT

问题描述

在学习《汇编语言(第三版)王爽 著》过程中,我们整理出该部分笔记:1)便于日后查阅;2)将我们记忆错误的地方,整理下来,形成对照;

该部分笔记将记录:在 x86 中,常用指令、使用说明,以及相关知识点。

注意事项

该部分的笔记:旨在记录我们理解错误的内容,不能作为汇编语言的学习教程。

解决方案

Classification of Instruction Sets

我们使用 ORACLE/x86 Assembly Language Reference Manual/3.2 General-Purpose Instructions 分类方法,按照该分类进行学习笔记的整理。

关于指令分类:
1)在处理器厂商的手册中,并没有对指令集分类,因此我们也不打算按分类整理指令;
2)但是,在分类列表中,我们可能会添加“类别”列,以辅助我们记忆;
3)指令的分类,参考 ORACLE/x86 Assembly Language Reference Manual 文档;

00.Data Transfer Instructions
01.Binary Arithmetic Instructions
02.Decimal Arithmetic Instructions
03.Logical Instructions
04.Shift and Rotate Instructions
05.Bit and Byte Instructions
06.Control Transfer Instructions
07.String Instructions => 串操作指令
08.I/O Instructions
09.Flag Control (EFLAG) Instructions => 标志处理指令
10.Segment Register Instructions
11.Miscellaneous Instructions

MUL – 乘法

指令格式:
MUL <register>
MUL <memory location>

对于乘数:
两个乘数:要么全为 8-bit ;要么全为 16-bit ;
当两个乘数全为 8-bit 时:一个乘数放在 AL 中;一个乘数放在 8-bit 寄存器内存字节单元 中;
当两个乘数全为 16-bit 时:一个乘数放在 AX 中;一个乘数放在 16-bit 寄存器内存字单元 中;

对于结果:
当两个乘数全为 8-bit 时:结果保存在 AX 中;
当两个乘数全为 16-bit 时:结果的高位保存在 DX 中;结果的低位保存在 AX 中;

使用示例:

; 示例一、计算 100x10
; 此时乘数全为 8 位
mov al, 100
mov bl, 10
mul bl ; 计算结果保存在 AX 中

; 示例二、计算 100x10000
; 此时乘数 10000 需要使用 16 位寄存器
mov ax, 100
mov bx, 10000
mul bx
; 计算结果:低位保存在 AX 中;高位保存在 DX 中

; 示例三、使用内存单元
; 将内存地址 ds:[0] 的字单元乘以 10000
mov ax, 10000
mul word ptr ds:[0] ; 结果保存在 AX 中

DIV – 除法

对于除数、被除数:
除数有 8-bit 和 16-bit 两种,保存在 寄存器 或者 内存单元 中。
当除数为 8-bit 时,被除数为 16-bit ,默认存放在 AX 寄存器中
当除数为 16-bit 时,被除数为 32-bit ,在 DX 中存放高 16-bit ,在 AX 中存放低 16-bit 。

对于结果:
当除数为 8-bit 时,计算结果为 8-bit ,在 AL 中存放商,在 AH 中存放余数
当除数为 16-bit 时,计算结果为 8-bit ,在 AX 中存放商,在 DX 中存放余数

使用示例:

; 示例一、100001/100
mov dx, 1
mov ax, 86a1H
mov bx, 100
div bx ; 商 => ax,余数 => dx

; 示例二、1001/100
mov ax, 1001
mov bl, 100
div bl ; 商 => al,余数 => ah

INT – 引发中断

指令格式:
int n,其中 n 为中断类型码

执行过程:
1)获取中断类型码(n) => 用于在查找中断向量表中定位中断程序入口
2)将标志寄存器入栈
3)IF = 0,TF = 0;
4)先将 CS 入栈,再将 IP 入栈;
5)(IP) = (4 * n), (CS) = (4 * n + 2)

其他内容:
Can an x86 assembly interrupt service routine call another interrupt?

MOVSB, MOVSW – 串传送

将字节(MOVSB)或字(MOVSW)从 ds:[si] 移动到 es:[di] 中,并增加(DF=0)或较少(DF=1) si 与 di 寄存器

指令格式:
MOVSB

执行过程:

((ES) * 16 + (DI)) = ((DS) * 16 + (SI))

if DF == 0
	(si) = (si) + 1, (di) = (di) + 1

if DF == 1
	(si) = (si) - 1, (di) = (di) - 1

指令 MOVSW 类似,但是移动字,同时以 2 为步长修改 si di 寄存器。

REP – 重复

根据 cx 的值,重复执行串传送指令

指令格式:
REP MOVSB
REP MOVSW

执行过程(相当于):

l:	MOVSB
	loop l

SHL / SHR – 逻辑位移

SHR,对目的操作数进行位移。指令格式:

Instruction Description
SHR r8/m8, 1  
SHR r16/m16, 1  
SHR r8/m8, imm8  
SHR r16/m16, imm8  
SHR r8/m8, CL  
SHR r16/m16, CL  

相关链接

Wikipedia/x86 instruction listings
ORACLE/x86 Assembly Language Reference Manual

参考文献

《汇编语言(第三版)王爽 著》
Wikipedia/FLAGS register
百度文库/汇编指令分类介绍
Wikipedia/x86 instruction listings
ORACLE/x86 Assembly Language Reference Manual