ghdhair100
Cholerny Spammer
Joined: 15 Dec 2010
Posts: 1829
Read: 0 topics
Location: England
|
Posted: Thu 2:47, 10 Mar 2011 Post subject: 80x86 指令系统 - &am |
|
|
数据传送指令
mov 传送
movsx 带符号扩展
movzx 带0扩展
push
pop
pusha 进栈顺序: ax.cx.dx.bx.sp(变化之前的sp).bp.si.di
popa
xchg 交换
输入输出指令
in 如: IN AL, PORT 或 IN AL, DX 使用PORT指定的端口或DX中存放的端口
out 同上
取源操作数的有效地址
LEA 将源操作数的有效地址送到目的.
如: LEA BX , [BX+SI+0F62H]
LEA BX , LIST 相当与 MOV BX , OFFSET LIST
加载到目的寄存器和一个段寄存器
LDS
LES
LFS //386后加入
LGS //386后加入
LSS //386后加入
把源地址存放的内容送到目的寄存器.再将源地址+2存放的内容送指令对应的段寄存器.
例如: LES DI [BX] 则执行 将(DS*16+BX)送DI(目的寄存器) 再将(DS*16+BI+2)送ES.
传送标志寄存器
LAHF 标志送AH (标志为FLAGS的低字节)
SAHF AH送标志
PUSHF 标志(16位) 进栈
POPF
PUSHFD 标志(32位) 进栈 .实际进栈的是 EFLAGS AND 0FCFFFFH.(清除VM和RF标志)
POPFD
类型转换
CBW 字节转换到字. 带符号扩展(即AL的符号位扩展到AH)
CWD 字到双字(AX存放源字. 带符号扩展后AX存放低位字.用DX存放高位字.)
CWDE 字到双字(从AX扩展到EAX)
CDQ 双字到4字 (EAX 扩展到 EDX和EAX)
BSWAP 交换字节序(反序存放). 如 BSWAP EAX
3.3.2 算术指令
加
ADD
ADC 带进位加 如: ADC AX, BX 为将AX+BX+CF放入AX
INC 加1 (这个指令不影响标志)
XADD 交换并相加
减
SUB
SBB 带借位减
DEC 减1
NEG 求补(即按位取反后加1)
CMP 比较(相减后并不保存结果.只根据结果设置标志)
CMPXCHG 交换并比较
CMPXCHG8 交换并比较8字节
乘
MUL 无符号乘法
IMUL 带符号乘法
目的操作数必须是累加器
而且8位相乘得16位存入AX ,[link widoczny dla zalogowanych], 16位相乘存DX+AX
结果比原来要长一倍.但可以根据CF和OF两个标志来判断结果值的大小是否真的要长1倍.
除
DIV 无符号除法. 被除数的长度为除数的2倍且放在AX+DX中. 结果商放入被除数的低位.余数放高位.
IDIV 带符号除法. 余数符号同被除数一样.
逻辑指令
AND
OR
NOT
XOR 按位异或
TEST 测试源操作数中指定的位. 如要测试10001011的第1.2两位. TEST 10001011,00000011.结果为真.
除了NOT.其它的都影响标志.
位测试 / 修改指令
BT 测试指定位(即将目的操作数的某位送到CF)
BTS 测试并置1
BTR 测试并置0
BTC 测试并置反
位扫描指令
即从左向右或从右向左寻找源操作数中第一个为1的位..若找不到则ZF置1.
否则ZF置0并将该位的位置放入目的寄存器.
BSF 从右向左
BSR 从左向右
移位指令
SHL 逻辑左移 如 SHL EAX 10
SHR 逻辑右移
SAL 算术左移
SAR
SOL 循环左移
SOR
RCL 带进位循环左移. 即每次移位的最高位送CF
RCR
SHLD 双精度左移 如 SHLD AX,DX,5
SHRD
串处理指令
MOVS 串传送 操作数用SI和DI(变址寄存器). 传送方向根据DF .
变址SI和DI的加减值为1(字节),[link widoczny dla zalogowanych],2(字),4(双字). 如:
MOVS ES::BYTE PTR[DI],DS:[SI];在BYTE PTR指定了操作的是字节.所以变址每次加减1
执行的操作: ((DI)) <- ((SI)) 再 DI+1 SI+1
MOVSB 传送字节
MOVSW 传送字
MOVSD 传送双字
CMPS 串比较 串处理指令一般与REP循环指令连用.退出循环后.可根据CX(计数器)和SI(或DI)的值得出结果.
SCAS 串扫描 同上.
LODS 从串取 将源变址寄存器指向的存储单元的内容送AL/AX/EAX , 一般不与REP连用
STOS 存入串 将AL/AX/EAX内容送目的变址寄存器指向的存储单元 . 若与REP连用则是填充一段内存
INS 串输入 输入一个字符.如INS DST,DX(DX指定端口号). 若与REP连用表示输入一段字符.
OUTS 串输出 输出一个字符. 与REP连用是输出一段字符.
循环指令
REP 重复操作直到 计数寄存器值为0
REPE/REPZ 相等/为零 则重复. 即 CX或 ZF为零时停止重复
REPNE/REPNZ 不相等/不为零 则重复.
控制转移指令
JMP 无条件转移指令
段内直接转移:
JMP SHORT OPR
短转移.执行 (IP) <- (IP)+8位移量
JMP NEAR OPR
近转移.执行 (IP) <- (IP)+16位移量
段内间接转移:
JMP WORD PTR OPR
近转移. 执行 (IP) <- OPR所指单元的内容
段间直接远转移:
JMP FAR OPR
执行 (IP) <- OPR的偏移地址 (CS) <- OPR所在段的段地址
段间间接远转移:
JMP DWORD PTR OPR
执行 (IP) <- (EA) (CS) <- (EA+2)
条件转移指令
JZ(JE)/JNZ(JNE) 为0(相等) /不为0(不相等) 则重复. 测试 ZF
JS/JNS 测试 SF (符号)
JO/JNO 测试 OF (溢出)
JP(JPE)/JNP(JPO) 测试 PF (奇偶)
(以下几个测试比较无符号数结果的转移指令)
JB(JNAE,JC) / JNB(JAE,JNC) 测试 CF
JBE(JNA) / JNBE(JA) 测试 CF 和 ZF
(以下几个测试比较带符号数结果的转移指令)
JL(JNGE) / JNL(JGE) 测试 SF OF < / >=
JLE(JNG) / JNLE(JG) 测试 SF OF ZF > / <=
(下边的测试CX计数寄存器是否为0的转移指令)
JCXZ / JECXZ CX(ECX)为0则转移
根据标志来设置目的字节指令
SETZ(SETE) / SETNZ(SETNE) 根据ZF标志的值将目的字节置1 . 如 SETZ AX
SETS / SETNS 根据SF (符号)标志
SETO / SETNO 根据OF (溢出)标志
SETP(SETPE) / SETNP(SETNPO) 根据PF (奇偶)标志
SETC(SETB,SETNAE) / SETNC(SETNB,SETAE) 根据CF (进位)标志
(以下几个指令用于比较无符号数后的情况)
SETB(SETNAE,SETC) / SETNB(SETAE,SETNC)
SETBE(SETNA) / SETNBE(SETA)
(以下几个指令用于比较带符号数后的情况)
SETL(SETNGE) / SETNL(SETGE)
SETLE(SETNG) / SETNLE(SETG)
循环指令
若现在我们不用循环指令写一个循环程序. 如下:
mov cx, 10
AGAIN:
....循环体
DEC CX
JNZ AGAIN
为了简化上面的程序. 使用LOOP指令如下:
mov cx , 10
AGAIN:
.....循环体
LOOP AGAIN
可见LOOP代替了计数器CX自减指令和条件转移指令
LOOP 测试 CX 不为0 则循环
LOOPZ/LOOPE 测试CX不为0 且 ZF=1 则循环
LOOPNZ/LOOPNE 测试CX不为0 且 ZF=0 则循环
子程序
调用 CALL
段内直接时: PUSH(IP) (IP) <- (IP)+位移量
段内间接时: PUSH(IP) (IP) <- (EA)
段间直接时: PUSH(CS) PUSH(IP) (IP) <- 目的的偏移值 (CS) <- 目的的段地址
段间间接时: PUSH(CS) PUSH(IP) (IP) <- (EA) (CS) <- (EA+2)
返回 RET
段内返回: (IP) <- POP()
段内带立即数返回: 如 REP EXP
执行 : (IP) <- POP() (SP) <- (SP)+EXP //修改堆栈指针.
//用来清理栈上参数(在call前入栈的参数)
段间返回: (IP) <- POP() (CS) <- POP()
段间带立即数返回: 如: RET EXP
执行: (IP) <- POP() (CS) <- POP() (SP) <- (SP)+EXP //修改堆栈指针.
中断
程序执行期间.碰到有些情况时需要自动执行某一例程专门处理.
这些情况指的就是"中断". 碰到它执行的程序就是"中断例行程序".
中断分为
内部中断: 包括如除0错等.
外部中断: 主要用来处理CPU与IO的通信.
CPU响应中断时
像子程序调用一样要先将 IP 和 CS 入栈. 并要将 FLAGS 入栈. 从中断处理程序返回后恢复.
中断例行程序的入口地址称为"中断向量".
80x86的实模式下.存储器的最低1024字节存放了256个中断向量. 如下:
地址 内容
00000 类型0的IP //除0错
00002 类型0的CS
00004 类型1的IP //
00006 类型1的CS
中断指令
INT
格式 INT TYPE(中断类型)
执行的操作: PUSH (FlAGS) IF <- 0 TF <- 0 AC <- 0
PUSH (CS) PUSH (IP) (IP) <- (TYPE*4) (CS) <- (TYPE*4+2)
INTO
格式 INTO
若溢出则中断. 相当于若 OF=1 则 INT 4
IRET / IRETD
格式 IRET 或 IRETD
从中断返回. 其中IRET是16位版本. IRETD是32位版本.
执行的操作: (IP) <- POP() (CS) <- POP() (FLAGS) <- POP() //32位版本中用EIP EFLAGS
标志修改指令
CLC CF=0 进位
STC CF=1
CMC CF=-CL
CLD DF=0 方向
STD DF=1
CLI IF=0 中断
STI IF=1
杂项指令
NOP 无操作. 该指令的机器码占1字节.用来占个位置以便以后用其它指令代替.
HLT 停机
ESC 换码
WAIT 等待
LOCK 封锁.与其它指令连用时.用来维持总线的锁存信号.直到指令执行完毕.
BOUND 界限.若发现数组越界.则产生中断5. 否则继续执行下一条指令.
ENTER 建立堆栈帧
格式: ENTER imm16 , imm8 //其中第一个16位操作数指出堆栈帧的大小,[link widoczny dla zalogowanych],第2个8位是过程嵌套层数
执行的操作: PUSH (BP) (BP) <- (SP) //将改变前的SP保存在BP. (SP)<-(SP)-imm16
这个指令一般放在过程的入口点.建立的堆栈帧用来存放过程的局部变量.也便于过程的参数传递.
LEAVE 释放ENTER建立的堆栈帧
格式 LEAVE
执行的操作: (SP)<-(BP) (BP)<-POP()
这个指令用在RET之前.退栈.
Many years ago there lived an Emperor who was so exceedingly fond of fine new clothes that he spent vast sums of money on dress. To him clothes meant more than anything else in the world. He took no interes
related links:
[link widoczny dla zalogowanych]
The post has been approved 0 times
|
|