跟着写操作系统(汇编语言小录)

    上次在经过一番折腾之后,总算是把写操作系统的开发环境给搭建起来了,看了以下前面的程序,着实有些蛋疼的感觉阿,都是汇编,艾,普通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!


跟着写操作系统(汇编语言小录)

上一篇:linux命令--使用fsck修复文件系统


下一篇:linux命令解析--scp ssh