上次在经过一番折腾之后,总算是把写操作系统的开发环境给搭建起来了,看了以下前面的程序,着实有些蛋疼的感觉阿,都是汇编,艾,普通2b学校,平时上课不上汇编,怎么办呢,只好去图书馆接了一本《汇编语言与接口技术》,一直以来,都有这么一个想法,又想学得更多,又想学得更快,虽然知道这不是一个长久之计,怎么说也可以应付暂时的需求亚,就这么愉快的决定了。
准备对照两本书来研究算法,指令虽然找到了,但是发现后面的寄存器看都看不懂,算了,还是把汇编过一遍吧,这部,边看书边记录,下面吧我这几天来的总结列出来分享一下,同时也为了方便以后查阅(顺便说一下,这里所有的指令都另加了英文注释,个人认为这样的话比较容易记忆):
(一)标志位:
--------------------------------------------- | |NT|IOPL|OF|DF|IF|TF|SF|ZF| |AF| | |PF| |CF| --------------------------------------------- NT: nested task flag(286+) 嵌套任务标志 IF: interrupt enable flag 中断使能标志 AF: auxilary carry flag 辅助进位标志 IOPL: I/O privilege level(286+) I/O特权级 TF: trap flag 陷阱标志 PF: parity flag 奇偶标志 OF: overflow flag 溢出标志 SF: sign flag 注册标志 CF: carry flag 仅为标志 DF: direction flag 方向标志 ZF: zero flag 零标志位(二)寄存器
1、通用寄存器 AX(accumulator)、BX(base)、CX(count)、DX(data)这些寄存器可以字(16位)或字节(8位)单位形式访问; SP(stack pointer)、BP(base pointer)、SI(source index)、DI(destination index),这些寄存器只能以字(16位)单位形式访问。 2、专用寄存器 IP(instruction pointer)、SP(stack pointer);; FLAGS又称PSW(program status word)分为: ① 条件码 OF(overflow)、SF(sign)、ZF(zero)、CF(carry)、AF(auxiliary)、PF(parity) ② 控制标志 DF(direction) ③ 系统标志位 TF(trap)、IF(interrupt)、IOPL(I/O privilege level) 3、段寄存器 CS(code)、DS(data)、SS(stack)、ES(extra)
(三)汇编指令
一、数据传送指令 1.通用数据传送指令. MOV----> move: 1.由立即数或寄存器位数决定传递的位数; 2.目的操作数和源操作数不能都是存储器操作数; 3.不能用CS,IP作为目的操作数,即两个寄存器内容不能随意改变; 4.不允许在段寄存器间传输数据(MOV DS,ES是错误的); 5.不允许用立即数作为目的操作数; 6.不能向段寄存器传送立即数,可通过CPU的通用寄存器AX完成. MOVSX---->extended move with sign data MOVZX---->extended move with zero data PUSH---->push (POP---->pop) 压入(送出)存储器操作数,寄存器操作数或立即数(16位寄存器或存储器) 注意: 1.只允许按字访问堆栈,即两类指令操作数必须为16位寄存器或存储单元操作数 2.CS不能作为目的操作数 PUSHA---->push all POPA---->pop all PUSHAD---->push all data POPAD---->pop all data BSWAP---->byte swap XCHG---->exchange 可实现通用寄存器及通用寄存器和存储器之间数据交换 CMPXCHG---->compare and change XADD---->exchange and add XLAT---->translate 格式: XLAT label XLAT ;AL<-DS:((BX) + (AL)) 功能:转换表中一个字节代换AL寄存器中的内容可用于码转换
2.输入输出端口传送指令. IN---->input 累加器, 端口 把一个字节/字由输入端口传送到AL/AX OUT---->output 端口, 累加器 3.目的地址传送指令. LEA r16, mem---->load effective address 要求:r16为一个16位通用寄存器, mem为存储单元 功能:将有效地址(地址偏移量)送至通用寄存器,而非将存储单元内容送至通用寄存器 注意: 1.两个操作数不能同时为存储器操作数 2.任一个操作数都不能使用段寄存器,也不能使用立即数 LEA BX, VARWORD 等效 MOV BX, OFFSET VARWORD 区别在于后者用伪指令OFFSET,由编译器在编译时赋值,而前者在执行时赋值 LDS---->load DS (LES---->load ES) 将内存中连续4个字节内容高16位送到DS(ES)以及低16位送至指定的通用寄存器 注意:dest必须为通用寄存器之一,src必须为内存操作数 例: 1.LDS DI, [2130] ;将2130h和2131h单元内容送DI,2132H和2133h单元送DS 2.EXDWORD DD 12345678H LDS SI, EXDWORD ;将1234H送DS, 5678h送SI LFS---->load FS LGS---->load GS LSS---->load SS
4.标志传送指令. LAHF---->load AH from flag 取标志指令,将标志寄存器低8位送AH SAHF---->save AH to flag 存标志指令,将AH内容送至标志寄存器低8位 PUSHF---->push flag POPF---->pop flag PUSHD---->push dflag POPD---->pop dflag 二、算术运算指令 20条算术运算指令,除加减1外都是双操作数指令,双操作数必须有一个在寄存器中,双操作数目的操作数以及单操作数不允许使用立即数 ADD---->add 1.不允许两个存储器单元内容相加; 2.不允许两个段寄存器之间相加; 3.对标志位有影响,主要是CF,ZF,OF,SF ADC---->add with carry 在完成两个字或字节相加的同时,还要考虑CF的值来判断是否加1 源操作数和目的操作数不能同时为存储单元,段寄存器不能进行算数运算 INC reg/mem ---->increase 1 要求:reg是8或16位的通用寄存器,mem为8或16位的存储单元(不能为立即数) 源操作数加1再送回,一般用于循环程序指针修改,只有一个操作数; 影响AF,OF,PF,SF和ZF,不影响CF,将操作数视为无符号数 SUB---->substract 要求同ADD指令 SBB---->substract with borrow 要求同ADC
DEC---->decrease 1 要求同INC NEG---->negative 将操作数取补后送回源操作数 操作数可以为8或16位通用寄存器或存储器操作数,不能为立即数 注意:只有操作数为0才使CF=0,否则CF=1,若操作数值为-128(80H)或-32768(8000H),执行取补指令结果没有变化,但此时溢出标志OF=1 CMP dest, src ---->compare dest - src不送回结果,根据结果置标志位 组合的BCD调整指令: DAA---->decimal add with adjust 对在AL中的和(由两个组合BCD码相加)进行调整产生一个组合的BCD码 若AL中的低四位在A-F之间,或AF=1,则AL<-(AL)+6,且AF位置1 --------高四位-------------CF=1----AL<-(AL)+60H--CF----1 DAS---->decimal adjust on substract 对在AL中的差(由两个组合BCD码相减)进行调整产生一个组合的BCD码 若AL中的低四位在A-F之间,或AF=1,则AL<-(AL)-6,且AF位置1 --------高四位-------------CF=1----AL<-(AL)-60H--CF----1 影响标志AF,CF,PF,SF和ZF,不影响OF 未组合的BCD调整指令: AAA---->ascII add with adjust 对ADD指令运算后AL内容进行调整 AAS---->ascII adjust on substract --SUB------------------------ AAM---->ascII adjust on multiplication --MUL----------AX中乘积进行BCD调整 AAD---->ascII adjust on divide 调整DIV前AH,AL中除数,以便除法得到商为有效未组合BCD数 AAA,AAS会影响AF,CF,对OF,PF,SF和ZF没有意义,需要紧跟调整命令后
MUL---->multiplication 不带符号8或16位二进制乘法 格式 MUL REG/MEM ----> 隐含的AL/AX乘REG/MEM MUL DEST, SRC DEST可为8或16位通用寄存器或存储器,src可为8或16位通用寄存器,存储单元或立即数,但dest,src不能同时为存储器 IMUL---->integer multiplication 要求同MUL,带符号乘法 DIV---->divide 要求同mul 无符号字或字节相除时,所得商及余数均为无符号数,分别放在AL和AH中,无符号双字或字相除,所得商余数也位无符号,放在AX和DX中 IDIV---->integer divide 要求同div,带符号除法 CBW---->change byte to word 将AL中单字节数的符号扩展到AH中;若AX<80H,则0->AH;若AL>=80H,则FFH->AH CWD---->change word to double word 将AX中单字节数的符号扩展到DX中;若AX<8000H,则0->DX;若AL>=8000H,则FFFFH->DX CWDE---->change word to double word with sign to EAX CDQ---->change double word to quadrate word
三、逻辑运算指令 AND---->and OR---->or XOR---->xor Exclusive OR 以上三个src和dest不能同时为存储单元,段寄存器不能进行逻辑运算 NOT---->not TEST---->test 按位与,只存标志,不存结果 SAL reg/mem,1/CL ---->arithmatic shift left 算术左移1次或CL指定的次数 SAR reg/mem,1/CL ---->arithmatic shift right --右------------------- SHL ------------ ----->shift left 逻辑左移---------------- SHR ------------ --->shift right ----右------------------ ROL ------------ --->rotate left 循环左移---------------- ROR ------------ --->rotate right ----右------------------ RCL ------------ ---->rotate left with carry 带进位 ROL RCR ------------ ---->rotate right with carry 带进位 ROR
四、串指令 MOVS---->move string CMPS---->compare string SCAS---->scan string LODS---->load string STOS---->store string 以上指令后加B表字节,加W表字 REP---->repeat (CX<-CX-1,=0为止) REPE---->repeat when equal CX或ZF=0停止执行 REPZ---->repeat when zero flag 同上 REPNE---->repeat when not equal CX或ZF=0停止执行 REPNZ---->repeat when zero flag 同上 以上指令不能单独使用,只能加在串操作指令前来控制跟在其后的字符串操作指令,使之重复执行,重复前缀不影响标志位 REPC---->repeat when carry flag REPNC---->repeat when not carry flag 五、程序转移指令 1>无条件转移指令(长转移) JMP---->jump CALL---->call CALL DST:段内直接调用,DST为子程序名 CALL SRC:段内间接调用,SRC为16位寄存器或各种寻址方式的存储器操作数 CALL DST:段间直接调用,DST给出子程序入口地址完整信息(段基址CS偏移量IP) CALL SRC:段间间接调用,SRC为各种寻址方式的存储器操作数 RET---->return 段内返回:把抱回堆栈断点偏移送入指令指针寄存器IP,返回调用程序处继续执行 段间返回:段地址送至CS寄存器-----------------IP,---------- RET n:最后SP<-SP+n RETF---->return far
2>条件转移指令(短转移,-128到+127的距离内) -------------无符号数条件转移-------------------------- JA/JNBE---->jump when above/jump when below or equal JAE/JNB---->jump when above or equal/jump when not below JB/JNAE---->jump when below/jump when not above or equal JBE/JNA---->jump when below or equal/jump when not above JC---->jump when has carry flag JNC---->jump when not has carry flag JE/JZ---->jump when equal/jump when has zero flag JNE/JNZ---->jump when not equal/jump when not has zero flag JNP/JPO---->jump when not has parity/flag/jump when parity flag is odd JP/JPE---->jump when has parity flag/jump when parity flag is even -------------带符号数条件转移-------------------------- JG/JNLE---->jump when greater/jump when not less or equal JGE/JNL---->jump when greater or equal/jump when not less JL/JNGE---->jump when less/jump when not greater or equal JLE/JNG---->jump when less or equal/jump when not greater JNO---->jump when not has overflow flag JNS---->jump when not has sign flag JO---->jump when has overflow flag JS---->jump when has sign flag --------------根据ECX中值决定转移指令格式及功能-------- JCXZ---->jump when CX is zero JECXZ---->jump when ECX is zero
3>循环控制指令(短转移) LOOP---->loop 现将CX减1,判断为0则退出循环 LOOPE---->loop equal LOOPZ---->loop zero 执行时,将CX寄存器内容减1会送CX寄存器,ZF不受CX减1影响 if(CX!=0 && ZF==1){ 转移到目的标号执行,IP<-IP + 偏移量 }else if (CX!=0 && ZF==0){ 停止循环,按指令顺序执行 }else { 停止循环,按指令顺序执行 } LOOPNE---->loop not equal LOOPNZ---->loop not zero 执行时,将CX寄存器内容减1会送CX寄存器,ZF不受CX减1影响 if(CX!=0 && ZF==0){ 转移到目的标号执行,IP<-IP + 偏移量 }else if (CX!=0 && ZF==1){ 停止循环,按指令顺序执行 }else { 停止循环,按指令顺序执行 }
4>中断指令 INT n ---->interrupt n为中断类型码(0-255),n确定即可到0000H段中偏移地址4*n开始4个单元找到该程序入口地址 1.标志寄存器压入堆栈保存,SP<-SP-2,SS:[SP]<-标志寄存器内容 2.禁止新的可屏蔽终端和单步中断,IF<-0,TF<-0 3.断点地址压入堆栈保存,SP<-SP-2,SS:(SP)<-CS,SP<-SP-2,SS:(SP)<-IP 4.取中断服务程序起始地址,CS<-0000H:[4n+3]和0000H:[4n+2]内容,IP<-0000H:[4n+1]和0000H:[4n]的内容 INTO---->overflow interrupt 若OF=1启动中断子程序(INT N,其中N=4),OF=0则无操作 1.标志寄存器压入堆栈保存,SP<-SP-2,SS:[SP]<-标志寄存器内容 2.禁止新的可屏蔽终端和单步中断,IF<-0,TF<-0 3.断点地址压入堆栈保存,SP<-SP-2,SS:(SP)<-CS,SP<-SP-2,SS:(SP)<-IP 4.取中断服务程序起始地址,CS<-0000H:[0012H],IP<-0000H:[000AH] IRET---->interrupt return 执行中断返回指令时,自动完成断点出战(CS出战,IP出战)和flags出栈 1.断点地址出栈恢复,IP<-SS:(SP),SP<-SP+2,CS<-SS:(SP),SP<-SP+2 2.标志寄存器出栈恢复,标志寄存器<-SS:(SP),SP<-SP+2
5>处理器控制指令 HLT---->halt 使处理器暂时停止执行后继指令,直到不可屏蔽中断NMI发生,可屏蔽中断INTR被识别或处理器复位为止 WAIT---->wait 等待8086信号线上!TEST有效信号,=1表CPU处于等待状态,并继续执行WAIT指令,每隔5个时钟周期测试一次,一旦!TEST=0结束 ESC---->escape 使某个协处理器以从CPU取得的操作数进行处理 LOCK---->lock 总线锁定前缀,在执行带有LOCK前缀的命令后,禁止其他处理器占用总线 NOP---->no operation 执行空操作,只会引起IP的变化,用于填充内存形成正确转移地址和延时作用 STC---->set carry CF<-1 CLC---->clear carry CF<-0 CMC---->carry make change CF取反 STD---->set direction DF<-1 CLD---->clear direction DF<-0 STI---->set interrupt IF<-1 CLI---->clear interrupt IF<-0
六、伪指令 DW---->definw word PROC---->procedure ENDP---->end of procedure SEGMENT---->segment ASSUME---->assume ENDS---->end segment END---->end Move) MOVC (Move Code) MOVX (Move External) XCH (Exchange) PUSH POP AJMP (Absolute Jump) LJMP (Long Jump) SJMP (Short Jump) JMP (Jump Indirect) JZ (Jump Zero) JNZ (Jump Not Zero) JC (Jump if Carry) JNC (Jump if Not Carry) JB (Jump if Bit is set) JNB (Jump if Not Bit) JBC (If Bit is set and Clear Bit) CJNE (Compare and Jump if Not Equal) DJNZ (Decrement and Jump if Not Zero)
ACALL (Absolute Call) LCALL (Long Call) RET (Return) NOP (No Operation) ADD ADDC (Add with Carry) SUBB (Substract with Borrow) MUL (Multiply) DIV (Divide) INC (Increment) DEC (Decrement) ANL (Logical AND) ORL (Logical OR) XRL (Logical Exclusive OR) CPL (Complement) CLR (Clear) SEBT (Set Bit) RL (Rotate Left) RR (Rotate Right) RLC (Rotate Left throught the Carry flag) RRC (Rotate Right throught the Carry flag) XCHD SWAP DA (Decimal Adjust) ORG (Origin) DB (Define Byte) DW (Define Word) EQU (Equal) DATA XDATA (External Data) BIT END
中英文对照基本来自这篇文章,当然中文注释部分是从前文提到的那本汇编书上找到依次找到,记录一下,以供查阅。
恩,ok,指令大致看过一遍了,接下来把看一下后面一个章节的汇编语言程序设计,就回归我的操作系统的实现。perfect!