汇编 |
基本简介编辑本段回目录
汇编 |
在计算机最大的领域为IT软件,也是常说的Windows编程,在熟练的程序员手里,使用汇编语言编写的程序,运行效率与性能比其它语言写的程序是成倍的优秀,但是代价是需要更长的时间来优化,如果对计算机原理及编程基础的扎实,实在是得不尝失,对比现在的软件开发,已经是市场化的软件行业,加上高级语言的优秀与跨平台,一个公司不可以让一个团队使用汇编语言来编写所有的东西,花上几倍甚至几十倍的时间,不如使用其它语言来完成,只要最终结果不比汇编语言编写的差太多,就能抢先一步完成,这是市场经济下的必然结果。
没有程序员敢断定汇编语言是不需要学的,一个不懂汇编语言的程序员,只是三流的程序,这是大部分人的共识,同时,技术精湛的汇编程序员,已经脱离软件开发,挤身于工业电子编程中,一个电子工程师,主要开发语言就中汇编,c语言使用只占极少部分,而电子开发工程师是千金难求,在一些工业公司,一个核心的电子工程师比其它任何职员待遇都高,对比起来,一般电子工程师待遇是程序员的十倍以上。这种情况是因为现在学习汇编的人虽然也不少,但是真正能学到精通的却不多,它难学,难用,适用范围小,虽然简单,但是过于灵活,学习过高级语言的人去学习汇编比一开始学汇编的人难得多,但是学过汇编的人学习高级语言却很容易,简从繁易,繁从简难。
汇编语言是程序员的必修语言。
常用命令编辑本段回目录
汇编 |
MOVDST,SRC//Byte/Word
执行操作:dst=src
1、目的数可以是通用寄存器,存储单元和段寄存器(但不允许用CS段寄存器)。
2、立即数不能直接送段寄存器。
3、不允许在两个存储单元直接传送数据。
4、不允许在两个段寄存器间直接传送信息。
PUSH入栈指令及POP出栈指令:堆栈操作是以"后进先出"的方式进行数据操作。
入栈的操作数除不允许用立即数外,可以为通用寄存器,段寄存器(全部)和存储器。入栈时高位字节先入栈,低位字节后入栈。
出栈操作数除不允许用立即数和CS段寄存器外,可以为通用寄存器,段寄存器和存储器。执行POPSS指令后,堆栈区在存储区的位置要改变。执行POPSP指令后,栈顶的位置要改变。
XCHG(eXCHanG)交换指令:将两操作数值交换。
XCHGOPR1,OPR2//Byte/Word
执行操作:Tmp=OPR1OPR1=OPR2OPR2=Tmp
1、必须有一个操作数是在寄存器中
2、不能与段寄存器交换数据
3、存储器与存储器之间不能交换数据。
换码指令编辑本段回目录
汇编 |
XLAT(OPR可选)//Byte
执行操作:AL=(BXAL)
指令执行时只使用预先已存入BX中的表格首地址,执行后,AL中内容则是所要转换的代码。
LEA(LoadEffectiveAddress)有效地址传送寄存器指令
LEAREG,SRC//指令把源操作数SRC的有效地址送到指定的寄存器中。
执行操作:REG=EAsrc
注:SRC只能是各种寻址方式的存储器操作数,REG只能是16位寄存器
MOVBX,OFFSETOPER_ONE等价于LEABX,OPER_ONE
MOVSP,[BX]//将BX间接寻址的相继的二个存储单元的内容送入SP中
LEASP,[BX]//将BX的内容作为存储器有效地址送入SP中
LDS(LoadDSwithpointer)指针送寄存器和DS指令
LDSREG,SRC//常指定SI寄存器。
执行操作:REG=(SRC),DS=(SRC2)//将SRC指出的前二个存储单元的内容送入指令中指定的寄存器中,后二个存储单元送入DS段寄存器中。
LES(LoadESwithpointer)指针送寄存器和ES指令
LESREG,SRC//常指定DI寄存器
执行操作:REG=(SRC),ES=(SRC2)//与LDS大致相同,不同之处是将ES代替DS而已。
LAHF(LoadAHwithFlags)标志位送AH指令
LAHF//将PSW寄存器中的低8位的状态标志(条件码)送入AH的相应位,SF送D7位,ZF送D6位。
执行操作:AH=PSW的低位字节。
SAHF(StoreAHintoFlags)AH送标志寄存器指令
SAHF//将AH寄存器的相应位送到PSW寄存器的低8位的相应位,AH的D7位送SF,D6位送ZF。
执行操作:PSW的低位字节=AH。
PUSHF(PUSHtheFlags)标志进栈指令
PUSHF//将标志寄存器的值压入堆栈顶部,同时栈指针SP值减2
执行操作:SP=SP-1,(SP)=PSW的高8位,SP=SP-1,(SP)=PSW的低8位
POPF(POPtheFlags)标志出栈指令
POPF//与PUSHF相反,从堆栈的顶部弹出两个字节送到PSW寄存器中,同时堆栈指针值加2
执行操作:PSW低8位=(SP),SP=SP1,PSW高8位=(SP),SP=SP1
输入输出指令(IN,OUT):只限于使用累加器AX或AL与外部设备的端口传送信息。
IN(INput)输入指令:信息从I/O通过累加器传送到CPU
INAL,PORT//直接的字节输入,PORT是外设端口编号(即端口地址),只能取00H~0FFH共256个端口地址。
INAX,PORT//直接的字输入,AX存储连续两个端口地址PORT1,PORT
INAL,DX//间接的字节输入,端口地址范围可通过DX设置为0000H~0FFFFH共65536个端口地址
INAX,DX//间接的字输入
OUT(OUTput)输出指令:信息从CPU通过累加器传送到I/O
OUTPORT,AL//直接的字节输出,PORT规定与IN指令相同。
OUTPORT,AX
OUTDX,AL//间接的字节输出
OUTDX,AX
MOVAL,05HOUT27H,AL//将字节05H传送到地址27H的端口
加法指令编辑本段回目录
汇编 |
执行操作:dst=dstsrc
1、两个存储器操作数不能通过ADD指令直接相加,即DST和SRC必须有一个是通用寄存器操作数。
2、段寄存器不能作为SRC和DST。
3、影响标志位AuxiliaryCrrayFlag,CarryFlag,OverflowFlag,ParityFlag,SignFlag和ZeroFlag,如下所示:
CF根据最高有效位是否有进(借)位设置的:有进(借)位时CF=1,无进(借)位时CF=0。
OF根据操作数的符号及其变化来设置的:若两个操作数的符号相同,而结果的符号与之相反时OF=1,否则为0。
ZF根据结果来设置:不等于0时ZF=0,等于0时ZF=1
SF根据结果的最高位来设置:最高位为0,则SF=0。
AF根据相加时D3是否向D4进(借)位来设置:有进(借)位时AF=1,无进(借)位时AF=0
PF根据结果的1的个数时否为奇数来设置:1的个数为奇数时PF=0,为偶数时PF=1
ADC(ADdwithCarry)带进位加法指令
ADCDST,SRC//Byte/Word
执行操作:dst=dstsrcCF//与ADD不同之处是还要加上进位标志位的值。
INC(INCreament)加1指令
INCOPR//Byte/Word
执行操作:OPR=OPR1
1、OPR可以是寄存器和存储器操作数,但不能是立即数和段寄存器
2、影响标志位OF,SF,ZF,PF和AF,不影响CF。
减法指令编辑本段回目录
汇编 |
SUBDST,SRC//Byte/Word
执行操作:dst=dst-src
1、DST和SRC寻址方式及规定与ADD相同。
2、影响全部标志位。
SBB(SuBtractwithBorrow)带借位减法指令
SBBDST,SRC//Byte/Word
执行操作:dst=dst-src-CF
DEC(DECrement)减1指令
DECOPR//Byte/Word
执行操作:OPR=OPR-1//除CF标志位,其余标志位都受影响。
NEG(NEGate)求补指令
NEGOPR
执行操作:opr=0-opr//将操作数按位求反后末位加1。
CMP(CoMPare)比较指令
CMPOPR1,OPR2
执行操作:OPR1-OPR2//与SUB指令一样执行运算,但不保存结果。
比较情况无符号数有符号数
A=BZF=1ZF=1
A>BCF=0&&ZF=0SF^OF=0&&ZF=0
A=BCF=0||ZF=1SF^OF=0||ZF=1
AAX=AL*src//字节运算时目的操作数用AL,乘积放在AX中
Word=>DX=AX*src//字运算时目的操作数用AX,DX存放乘积的高位字,AX放乘积的低位字
1、目的数必须是累加器AX或AL,指令中不需写出
2、源操作数SRC可以是通用寄存器和各种寻址方式的存储器操作数,而绝对不允许是立即数或段寄存器。
IMUL(sIgnedMULtiple)有符号数乘法指令
IMULSRC//与MUL指令相同,但必须是带符号数
DIV(unsignedDIVide)无符号数除法指令
DIVSRC//Byte/Word其中:SRC的规定同乘法指令MUL
执行操作:Byte=>AX/src//字节运算时目的操作数在AX中,结果的商在AL中,余数中AH中
Word=>DX,AX/src//字运算时目的操作数在DX高位字和AX低位字中,结果的商在AX中,余数在DX中
存储器操作数必须指明数据类型:BYTEPTRsrc或WORDPTRsrc
IDIV(sIgnedDIVied)有符号数除法指令
IDIVSRC//Byte/Word与DIV指令相同,但必须是带符号数
CBW(ConvertBytetoWord)字节转换为字指令
CBW执行操作:AL中的符号位(D7)扩展到8位AH中,若AL中的D7=0,则AH=00H,若AL中的D7=1,则AH=FFH。
CWD(ConvertWordtoDoubleword)字转换为双字指令
CWD执行操作:AX中的符号位(D15)扩展到16位DX中,若AX中的D15=0,则DX=0000H,若AX中的D15=1,则DX=FFFFH
调整指令编辑本段回目录
汇编 |
当计算机进行计算时,必须先把十进制数转换为二进制数,再进行二进制数运算,最后将结果又转换为十进制数输出。在计算机中,可用4位二进制数表示一位十进制数,这种代码称为BCD(BinaryCodedDecimal)。BCD码又称8421码,在PC机中,BCD码可用压缩的BCD码和非压缩的BCD码两种格式表示。
压缩的BCD码用4位二进制数表示一个十制数,整个十进数形式为一个顺序的以4位为一组的数串。非压缩的BCD码以8位为一组表示一个十进制数,8位中的低4位表示8421的BCD码,而高4位则没有意义。
压缩的BCD码调整指令
DAA(DecimalAdjustforAddition)加法的十进制调整指令
DAA执行操作:执行之前必须先执行ADD或ADC指令,加法指令必须把两个压缩的BCD码相加,并把结果存话在AL寄存器中。
DAS(DecimalAdjustforSubtraction)减法的十进制调整指令
DAS执行操作:执行之前必须先执行SUB或SBB指令,减法指令必须把两个压缩的BCD码相减,并氢结果存放在AL寄存器中。
非压缩的BCD码调整指令
AAA(ASCIIAdjustforAddition)加法的ASCII调整指令
AAA
执行操作:执行之前必须先执行ADD或ADC指令,加法指令必须把两个非压缩的BCD码相加,并把结果存话在AL寄存器中。
AAS(ASCIIAdjustforSubtraction)减法的ASCII调整指令
AAS执行操作:执行之前必须先执行SUB或SBB指令,减法指令必须把两个非压缩的BCD码相减,并氢结果存放在AL寄存器中。
串传指令编辑本段回目录
汇编 |
MOVB//字节串传送DF=0,SI=SI1,DI=DI1;DF=1,SI=SI-1,DI=DI-1
MOVW//字串传送DF=0,SI=SI2,DI=DI2;DF=1,SI=SI-2,DI=DI-2
执行操作:[DI]=[SI],将位于DS段的由SI所指出的存储单元的字节或字传送到位于ES段的由DI所指出的存储单元,再修改SI和DI,从而指向下一个元素。
在执行该指令之前,必须预置SI和DI的初值,用STD或CLD设置DF值。
MOVSDST,SRC//同上,不常用,DST和SRC只是用来用类型检查,并不允许使用其它寻址方式来确定操作数。
1、目的串必须在附加段中,即必须是ES:[DI]
2、源串允许使用段跨越前缀来修饰,但偏移地址必须是[SI]。
STOS(STOreintoString)存入串指令
STOSDST
STOSB//存放字节串(DI)=AL
STOSW//存放字串(DI)=AX
执行品作:把AL或AX中的内容存放由DI指定的附加段的字节或字单元中,并根据DF值修改及数据类型修改DI的内容。
1、在执行该指令之前,必须把要存入的数据预先存入AX或AL中,必须预置DI的初值。
2、DI所指向的存储单元只能在附加段中,即必须是ES:[DI]
LODS(LOaDfromString)从串取指令
LODSSRC
LODSB//从字节串取AL=(SI)
LODSW//从字串取AX=(SI±1)(SI)
执行操作:把由SI指定的数据段中字节或字单元的内容送入AL或AX中,并根据DF值及数据类型修改SI的内容。
1、在执行该指令之前,要取的数据必须在存储器中预先定义(用DB或DW),必须预置SI的初值。
2、源串允许使用段超越前缀来改变数据存储的段区。
REP(REPeat)重复操作前缀
REPStringPrimitive//其中:StringPrimitive可为MOVS,STOS或LODS指令
执行操作:使REP前缀后的串指令重复执行,每执行一次CX=CX-1,直至CX=0时退出REP。
方向标志编辑本段回目录
汇编 |
CLD
执行操作:令DF=0,其后[SI],[DI]执行增量操作
STD(SeTDirectionflag)设置方向标志指令
STD
执行操作:令DF=1,其后[SI],[DI]执行减量操作
CMPS(CoMPareString)串比较指令
CMPSSRC,DST
CMPSB//字节串比较(SI)-(DI)
CMPSW//字串比较(SI1)(SI)-(DI1)(DI)
执行操作:把由SI指向的数据段中的一个字节或字与由DI指向的附加段中的一个字节或字相减,不保留结果,只根据结果置标志位。
SCAS(SCAnString)串扫描指令
SCASDST
SCASB
SCASW
执行操作:把AX或AL的内容与由DI指向的在附加段中的一个字节或字相减,不保留结果,根据结果置标志位。
AND,OR,XOR和TEST都是双字节操作指令,操作数的寻址方式的规定与算术运算指令相同。
NOT是单字节操作指令,不允许使用立即数。
逻辑运算均是按位进行操作,真值表如下:
AND(位与&)OR(位或|)XOR(位异或^)
1&1=11|1=11^1=0
1&0=01|0=11^0=1
0&1=00|1=10^1=1
0&0=00|0=00^0=0
A:逻辑运算指令
AND(and)逻辑与指令
ANDDST,SRC//Byte/Word
执行操作:dst=dst&src
1、AND指令执行后,将使CF=0,OF=0,AF位无定义,指令执行结果影响SF,ZF和PF标志位。
2、AND指令典型用法A:用于屏蔽某些位,即使某些位为0。
屏蔽AL的高4位:即将高4位和0000B相与,低4位和1111B相与
MOVAL,39H//AL=00111001B[39H]
ADDAL,0FH//AL=00001001B[09H]即00111001B[39H]&00001111B[0FH]=00001001B[09H]
3、AND指令典型用法B:取出某一位的值(见TEST)
逻辑指令编辑本段回目录
汇编 |
执行操作:dst=dst|src
1、OR指令执行后,将使CF=0,OF=0,AF位无定义,指令执行结果影响SF,ZF和PF标志位。
2、常用于将某些位置1。
将AL的第5位置1:
MOVAL,4AH//AL=01001010B[4AH]
ORAL,10H//AL=01011010B[5AH]即01001010B[4AH]|00010000B[10H]=01011010B[5AH]
XOR(eXclusiveOR)逻辑异或指令
XORDST,SRC//Byte/Word
执行操作:dst=dst^src
1、XOR指令常用于使某个操作数清零,同时使CF=0,清除进位标志。
2、XOR指令使某些位维持不变则与'0'相异或,若要使某些位取反则与'1'相异或。
将AL的高4位维持不变,低4位取反:
MOVAL,B8H//AL=10111000B[B8H]
XORAL,0FH//AL=10110111B[B7H]即10111000B[B8H]^00001111[0FH]=10110111B[B7H]
测试某一个操作数是否与另一确定操作数相等:
XORAX,042EH
JZ//如果AX==042EH,则ZF=TRUE(1),执行JZ。。。
NOT(not)逻辑非指令
NOTOPR//Byte/Word
执行操作:opr=~opr//~01100101[65H]=10011010[9AH]
1、操作数不能使用立即数或段寄存器操作数,可使用通用寄存器和各种方式寻址的存储器操作数。
2、NOT指令不影响任何标志位。
将AL各位取反:
MOVAL,65H//AL=01100101B[65H]
NOTAL//AL=10011010B[9AH]即~01100101B[65H]=10011010B[9AH]
TEST指令编辑本段回目录
汇编 |
执行操作:opr1&opr2
1、两个操作数相与的结果不保存,结果影响标志位PF,SF和ZF,使CF=0,OF=0,而AF位无定义。
2、TEST指令常用于在不改变原有的操作数的情况下,检测某一位或某几位的条件是否满足。只要令用来测试的操作数对应检测位为1,其余位为0,相与后判断零标志ZF值的真假。
检测某位是否为1:
令用来测试的操作数对应检测位为1,其余位为0,TEST指令后,若该位为1则JNZ。
TESTAL,000000001B//测试AL最低位是否为1:令用来测试的操作数对应检测位为1,其余位为0,执行TEST指令JNZTHER //最低位若为1,则ZF=FALSE(0),执行JNZTHER,否则执行下一条指令。
或者:先对操作数求反,令用来测试的操作数对应检测位为1,其余位为0,TEST指令后,若该位为1则JZ。
MOVDL,AL//将AL传送到DL,主要是不要影响AL的值。以下测试AL的b2位是否为1
NOTDL//先对操作数求反
TEST00000100B//令用来测试的操作数对应检测位为1,其余位为0,执行TEST指令
JZTHER//若AL的b2位为1,则ZF=TRUE(1),执行JZTHER
B:移位指令[所有的移位指令都影响标志位CF、OF、PF、SF和ZF。AF无定义。]
非循环逻辑移位:把操作数看成无符数来进行移位。
SHL(SHiftlogicalLeft)逻辑左移指令
SHLOPR,CNT//Byte/Word
执行操作:使OPR左移CNT位,并使最低CNT位为全0。
1、OPR操作数不能使用立即数或段寄存器操作数,可使用通用寄存器和各种方式寻址的存储器操作数。
2、移位次数由CNT决定。每次将OPR的最高位移出并移到CF,最低位补0。
MOVCL,7//若移位多次,先预置移位次数CL
SHLDX,CL//CNT可取1或CL寄存器操作数
SHR(SHiftlogicalRight)逻辑右移指令
SHROPR,CNT//Byte/Word
同SHL,每次将OPR的最低位D0移出并移到CF。最高位补0。
非循环算术移位:将操作数看成有符号数来进行移位。
SAL(ShiftArithmeticLeft)算术左移指令
SALOPR,CNT//Byte/Word
SAL指令与SHL指令完全相同
SAR(ShiftArithmeticRight)算术右移指令
SAROPR,CNT//Byte/Word
SAR指令每次移位时,将最高位移入次高位的同时最高位值不变,最低位D0移出并移到CF。
循环移位编辑本段回目录
汇编 |
ROLOPR,CNT//Byte/Word
每次移位时,最高位移出并同时移到CF和最低位D0。
ROR(ROtateRight)循环右移指令
ROROPR,CNT//Byte/Word
每次移位时,最低位D0移出并同时移到CF和最高位。
带进位循环移位指令
RCL(RotateLeftthroughCarry)带进位循环左移指令
RCLOPR,CNT//Byte/Word
RCR(RotateRightthroughCarry)带进位循环右移指令
RCROPR,CNT//Byte/Word
处理器控制指令
CLC(CLearCarry)进位位置0指令
CLC//执行操作后,CF=0
CMC(CoMplementCarry)进位位求反指令
CMC//执行操作后,CF=!CF
STC(SeTCarry)进位位置1指令
STC//执行操作后,CF=1
NOP(NoOperetion)无操作指令
NOP//此指令不执行任何操作,其机器码占一个字节单元
HLT(HaLT)停机指令
HLT执行操作后,使机器暂停工作,使处理器CPU处于停机状态,以等待一次外部中断到来,中断结束后,程序继续执行,CPU继续工作。
转移指令编辑本段回目录
汇编 |
名称格式执行操作
段内直接短跳转JMPSHORTOPRIP=IP8位偏移量
段内直接近转移JMPNEARPTROPRIP=IP16位偏移量
段内间接转移JMPWORDPTROPRIP=(EA)
段间直接转移JMPFARPTROPRIP=OPR偏移地址,CS=OPR段地址
段间间接转移JMPDWORDPTROPRIP=(EA),CS=(EA2)
1、无条件转移到指定的地址去执行从该地址开始的指令。
2、段内转移是指在同一代码段的范围内进行转移,只需改变IP寄存器内容。
3、段间转移则要转移到另一个代码段执行程序,此时要改变IP寄存器和CS段寄存器的内容。
条件转移指令:根据上一条指令所设置的条件码(标志位)来判断测试条件。
根据五个标志位:ZF、SF、OF、PF、CF的两种状态(0FALSE或1TRUE)产生10种测试条件。
NameFlagFlag==TRUE[1]Flag==FALSE[0]
ZeroFalgZFJZOPR//结果为零转移JNZOPR//结果不为零转移
SignFalgSFJSOPR//结果为负转移JNSOPR//结果为正转移
OverflowFlagOFJOOPR//溢出转移JNOOPR//不溢出转移
ParityFlagPFJPOPR//结果为偶转移JNPOPR//结果为奇转移
CarryFlagCFJCOPR//有进位转移JNCOPR//无进位转移
两个数比较:
情况指令满足条件指令满足条件
ABJACF==0&&ZF==0JGSF^OF==0&&ZF==0
测试CX转移指令
JCXZOPR//CX==0时转移
LOOP(LOOP)循环指令
LOOPOPR测试条件:CX≠0//OPR在程序中实际是个标号
LOOPZOPR测试条件:ZF==1&&CX≠0
LOOPNZOPR测试条件:ZF==0&&CX≠0
执行操作:先执行CX=CX-1,再检测上面的测试条件,如满足则IP=IP符号扩展的D8,不满足则退出循环。
过程调用及返回指令
CALL(CALL)过程调用指令
CALLDST//DST在程序中实际是子程序标号
执行操作:先将过程的返回地址(即CALL的下一条指令的首地址)存入堆栈,然后转移到过程入口地址执行子程序。
调用方式格式断点保护入栈情况过程入口地址
段内直接CALLNEARPTRPR1(SP-1)(SP-2)←IP,CS不进栈CS值保持不变,IP←DST
段内间接CALLWORDPTR(EA)(SP-1)(SP-2)←IP,CS不进栈CS值保持不变,IP←(EA)
段间直接CALLFARPTRPR1(SP-1)(SP-2)←CS,(SP-3)(SP-4)←IPIP←DST偏移地址,CS←DST段地址
段间间接CALLDWORDPTR(EA)(SP-1)(SP-2)←CS,(SP-3)(SP-4)←IPIP←(EA),CS←(EA2)
注:为了表明是段内调用,可使用NEARPTR属性操作符作说明。
RET(RETurn)子程序返回指令
RET
RETEXP//带立即数返回
子程序返回指令RET放在子程序末尾,它使子程序在执行完全部任务后返回主程序继续执行被打断后的程序。返回地址在子程序调用时入栈保存的断点地址-IP或IP和CS。
相关词条编辑本段回目录
MYSQL | IP | ICP | ALEXA | PR | SEO |
CGI | FSO | FTP | POP3 | WCM | ECM |
FLASH | WEB | GPU | CPA | DIV | CSS |
HTML | BBS | .NET | XML | AJAX | MD5 |