汇编笔记4

控制转移指令

无条件转移指令 JMP

条件转移指令    JZ/JNZ,JE/JNE,jS/JNS,JO/JNO,JP/JNP,JB/JNB,JL/JNL,JBE/JNBE,JLE/JNLE,JCXZ

循环指令   LOOP,LOOPZ/LOOPE,LOOPNZ/LOOPNE

子程序调用和返回指令 CALL,RET

中断与中断返回指令 INT,INTO,IRET

下面详细解释

1.无条件转移指令:

段内直接短转移:JMP SHORT OPR

           执行操作:(IP)←(IP)+8位位移量

段内直接近转移:JMP NEAR PTR OPR

           执行操作:(IP)←(IP)+16位位移量

段内间接转移:   JMP WORD PTR OPR

           执行操作:(IP)←(EA)

段间直接远转移:JMP FAR PTR

          执行操作:(IP)OPR的段内偏移地址

段间间接转移:   JMP DWORD PTR OPR

         执行操作:(IP)(EA)

                           (CS)←(EA+2)

分类
指 令
转 移 条 件
说 明
(Ⅰ)
JZ/JE
ZF=1
为零/相等, 则转移
JNZ/JNE
ZF=0
不为零/不相等, 则转移
JS
SF=1
为负, 则转移
JNS
SF=0
为正, 则转移
JO
OF=1
溢出, 则转移
JNO
OF=0
不溢出, 则转移
JP
PF=1
奇偶位为1, 则转移
JNP
PF=0
奇偶位为0, 则转移
JC
CF=1
进位位为1, 则转移
JNC
CF=0
进位位为0, 则转移
(Ⅱ)
JB/JNAE/JC
CF=1
低于/不高于等于, 则转移
JNB/JAE/JNC
CF=0
不低于/高于等于, 则转移
JBE/JNA
(CF ZF)=1
低于等于/不高于, 则转移
JNBE/JA
(CF ZF)=0
不低于等于/高于, 则转移
(Ⅲ)
JL/JNGE
(SF OF)=1
小于/不大于等于, 则转移
JNL/JGE
(SF OF)=0
不小于/大于等于, 则转移
JLE/JNG
((SF OF) ZF)=1
小于等于/不大于, 则转移
JNLE/JG
((SF OF) ZF)=0
不小于等于/大于, 则转移
(Ⅳ)
JCXZ
(CX)=0
CX的内容为0, 则转移

表 3.3  条件设置字节指令

表 3.4 单标志位条件转移指令

表 3.5 无符号数比较条件转移指令

两个例子

       LOOP  label    循环(loop)
  执行操作:① (CX)←(CX)-1

       ② 若(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束


  
LOOPZ/LOOPE label 为零/相等时循环(loop while zero,or equal)
  执行操作:① (CX)←(CX)-1

       ② 若ZF=1且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束


  
LOOPNZ/LOOPNE label 不为零/不等时循环(loop while nonzero,or not equal)
  执行操作:① (CX)←(CX)-1

       ② 若ZF=0且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束

汇编笔记3

与 REPE/REPZ(REPNE/REPNZ) 配合工作的 CMPS和SCAS

REPE / REPZ 相等/为零时重复执行串指令,(CX)=比较/扫描的次数
  执行操作:

  ① (CX)=0或ZF=0时,结束执行串指令,否则继续② ~ ④

  ② (CX)←(CX)-1

  ③ 执行串指令(CMPS或SCAS)

  ④ 重复执行①

REPNE / REPNZ 不等/不为零时重复执行串指令,(CX)=比较/扫描的次数

  执行操作:

  ① (CX)=0或ZF=1,结束执行串指令,否则继续② ~ ④

  ② (CX)←(CX)-1

  ③ 执行串指令(CMPS或SCAS)

  ④ 重复执行①


  REP对其后的串指令(MOVS或STOS)只有一个结束条件,即重复次数(CX)=0。在进行串比较和串扫描时,串指令前应加前缀REPE(REPZ)或REPNE(REPNZ),这两条重复前缀用重复次数(CX)和比较结果(ZF)来控制串指令的结束。当(CX)=0时,说明每个串数据都比较(或扫描)过了,此时串操作正常结束;当因ZF=1或0而结束串操作时,说明在满足比较结果相等或不等的条件下,可提前结束串操作。

好…..收获不小…又学到了几个字符和字符串比较的指令……怎么今天下午一点都不困呢..哈哈..不知道….不困就继续学吧…..

汇编指令总结[转贴]

对于计算机软件专业的学生,适当的学习一些汇编语言知识,我认为很重要,有助于你对于计算机底层工作的了解,帮助你更好的理解计算机高级语言,汇编原理,也对于学习操作系统很有帮助…

近来自己在学汇编语言… 整理总结了常用的一些指令,认为对于学习汇编的龙友会有一些帮助


以下内容均为个人整理…错误不当之处还望大家指出更正..谢谢..


每条指令 均按照

1、指令的汇编格式

2、指令的基本功能

3、指令的寻址方式

4、指令对标志位的影响

5、指令的特殊要求

这5条内容的形式来对每条指令进行归纳总结….

                        Author:DeepKen


—————————————————–

[数据传送指令]


一、通用数据传送指令


1、传送指令 MOV (move)


指令的汇编格式:MOV DST,SRC

指令的基本功能:(DST)<-(SRC) 将原操作数(字节或字)传送到目的地址。

指令支持的寻址方式:目的操作数和源操作数不能同时用存储器寻址方式,这个限制适用于所有指令。

指令的执行对标志位的影响:不影响标志位。

指令的特殊要求:目的操作数DST和源操作数SRC不允许同时为段寄存器;

目的操作数DST不能是CS,也不能用立即数方式。


2、进栈指令 PUSH (push onto the stack)

出栈指令 POP (pop from the stack)


指令的汇编格式:PUSH SRC ;POP DST

指令的基本功能:PUSH指令在程序中常用来暂存某些数据,而POP指令又可将这些数据恢复。

PUSH SRC (SP)<-(SP)-2 ;(SP)<-(SRC)

POP DST (DST)<-((SP));(SP)<-(SP)

指令支持的寻址方式:push 和 pop指令不能不能使用立即数寻址方式。

指令对标志位的影响:PUSH 和 POP指令都不影响标志位。

指令的特殊要求:PUSH 和 POP指令只能是字操作,因此,存取字数据后,SP的修改必须是+2 或者 -2;

POP指令的DST不允许是CS寄存器;


3、交换指令 XCHG (exchange)


指令的汇编格式:XCHG OPR1,OPR2

指令的基本功能:(OPR1)<->(OPR2)

指令支持的寻址方式:一个操作数必须在寄存器中,另一个操作数可以在寄存器或存储器中。

指令对标志位的影戏:不影响标志位。

指令的特殊要求:不允许使用段寄存器。


二、累加器专用传送指令


4、输入指令 IN (input)

输出指令 OUT (output)


指令的汇编格式:IN ac,port port<=0FFH

IN ac,DX port>0FFH

OUT port,ac port<=0FFH

OUT DX,ac port>0FFH

指令的基本功能:对8086及其后继机型的微处理机,所有I/O端口与CPU之间的通信都由输入输出指令IN和OUT来完成。IN指令将信息从I/O输入到CPU,OUT指令将信息从CPU输出到I/O端口,因此,IN和OUT指令都要指出I/O端口地址。

IN ac,port port<=0FFH (AL)<-(port)传送字节 或 (AX)<-(port+1,port)传送字

IN ac,DX port>0FFH (AL)<-((DX))传送字节 或 (AX)<-((DX)+1,(DX))传送字

OUT port,ac port<=0FFH (port)<-(AL)传送字节 或 (port+1,port)<-(AX)传送字

OUT DX,ac port>0FFH (DX)<-(AL)传送字节 或 ((DX)+1,(DX))<-(AX)传送字

指令对标志位的影响:不影响标志位。

指令的特殊要求:只限于在AL或AX与I/O端口之间传送信息。

传送16位信息用AX,传送8位信息用AL,这取决于外设端口的宽度。



5、换码指令 XLAT (translate)


指令的汇编格式:XLAT opr 或 XLAT

指令的基本功能:这条指令根据AL寄存器提供的位移量,将BX指使的字节表格中的代码换存在AL中。

(AL)<-((DS)*16+(BX)+(AL))

指令对标志位的影响:不影响标志位。

指令的特殊要求:所建字节表格的长度不能超过256字节,因为存放位移量的是8位寄存器AL。

opr为表格的首地址,因为opr所表示的偏移地址已存入BX寄存器,所以opr在换码指令中可有可无,有则提高程序的可读性。


三、地址传送指令


6、有效地址传送器 LEA (load effective address)


指令的汇编格式:LEA reg,src

指令的基本功能:LEA指令把源操作数的有效地址送到指定的寄存器,这个有效地址是由src选定的一种存储器寻址方式确定的。

指令支持的寻址方式:各种存储器寻址方式。

指令对标志位的影响:不影响标志位。

指令的特出要求:指令中reg不能是段寄存器;


7、指针送寄存器和DS LDS (load DS with point)

指针送寄存器和ES LES (load ES with point)

指令的汇编格式:LDS reg,src

LES reg,src

指令的基本功能:LDS和LES指令把确定内存单元位置的偏移地址送寄存器,段地址DS或ES。这个偏移地址和段地址(也称地址指针)是由src指定的两个相继字单元提供的。

LDS reg,src (reg)<-(src) (DS)<-(src+2)

LES reg,src (reg)<-(src) (ES)<-(src+2)

指令支持的寻址方式:src必须为存储器寻址方式

指令对标志位的影响:不影响标志位。

指令的特殊要求:指令中REG不能是段寄存器;


四、标志寄存器传送指令


8、标志寄存器的低字节送AH LAHF (load AH with FLAGS)


指令的汇编格式:LAHF

指令的基本功能:(AH)<-(FLAGS)0-7

指令对标志位的影响:不影响标志位


9、AH送标志寄存器低字节 SAHF(store AH into FLAGS)


指令的汇编格式:SAHF

指令的基本功能:(FLAGS)0-7<-(AH)

指令对标志位的影响:由装入值来确定标志位的值。


10、标志进栈 PUSHF (push the flags)


指令的汇编格式:PUSHF

指令的基本功能:(SP)<-(SP)-2 ((SP)+1,(SP))<-(FLAGS)0-15

指令对标志位的影响:不影响标志位。


11、标志出栈 POPF (pop the FLAGES)


指令的汇编格式:POPF

指令的基本功能:(FLAGS)0-15<-((SP)+1,(SP)) (SP)<-(SP)+2

指令对标志位的影响:由装入值来确定标志位的值。


[算术指令]


一、加法指令


12、加法指令 ADD (addition)


指令的汇编格式:add dst,src

指令的基本功能:(dst)<-(src)+(dst)

指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:SF=1 加法结果为负数(符号位为1)

SF=0 加法结果为正数(符号位为0)

ZF=1 加法结果为零

ZF=0 加法结果不为零

CF=1 最高有效位向高位有进位

CF=0 最高有效位向高位无进位

OF=1 两个同符号数相加(正数+正数 或 负数+负数),结果符号与其相反。

OF=0 两个不同符号数相加,或同符号数相加,结果符号与其相同。


13、带进为加法指令 ADC (add with carry)


指令的汇编格式:ADD dst,src

指令的基本功能:(dst)<-(src)+(dst)+CF

指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:SF=1 加法结果为负数

SF=0 加法结果为正数

ZF=1 加法结果为零

ZF=0 加法结果不为零

CF=1 最高有效位向高位有进位

CF=0 最低有效位相高位无进位

OF=1 两个同符号数相加,结果符号与其相反,

OF=0 两个同符号数相加,或同符号相加,结果符号与其相同


14、加1指令 INC (increament)

指令的汇编格式:INC opr

指令的基本功能:(opr)<-(opr)

指令支持的寻址方式 可以使用除立即数方式外的任何寻址方式

指令对标志位的影响:SF=1 加法结果为负数

SF=0 加法结果为正数

ZF=1 加法结果为零

ZF=0 加法结果不为零

OF=1 两个同符号数相加,结果符号与其相反,

OF=0 两个同符号数相加,或同符号相加,结果符号与其相同。


二、减法指令


15、减法指令 SUB (subtract)


指令的汇编格式:SUB dst,src

指令的基本功能:(dst)<-(dst)-(src)

指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:SF=1 减法结果为负数(符号位为1)

SF=0 减法结果为正数(符号位为0)

ZF=1 减法结果为零

ZF=0 减法结果不为零

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


16、带借位减法指令 SBB (subtract with borrow)


指令的汇编格式:SBB dst,src

指令的基本功能:(dst)<-(dst)-(src)-CF

指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:SF=1 减法结果为负数(符号位为1)

SF=0 减法结果为正数(符号位为0)

ZF=1 减法结果为零

ZF=0 减法结果不为零

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


17、减1指令 DEC (decrement)


指令的汇编格式:DEC opr

指令的基本功能:(opr)<-(opr)-1

指令支持的寻址方式:可以使用除立即数方式外的任何寻址方式。

指令对标志位的影响:SF=1 减法结果为负数(符号位为1)

SF=0 减法结果为正数(符号位为0)

ZF=1 减法结果为零

ZF=0 减法结果不为零

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


18、比较指令 CMP (compare)


指令的汇编格式:CMP opr1,opr2

指令的基本功能:(opr1)-(opr2),根据相减结果设置条件码,但不回送结果。

指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:SF=1 减法结果为负数(符号位为1)

SF=0 减法结果为正数(符号位为0)

ZF=1 减法结果为零

ZF=0 减法结果不为零

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


19、求补指令 NEG (negate)


指令的汇编格式:NEG opr

指令的基本功能:(opr)<- -(opr)

指令支持的寻址方式:可以使用除立即数方式外的任何寻址方式。

指令对标志位的影响:CF=1  不为0的操作数求补时

    CF=0  为0的操作数求补时

OF=1 操作数为-128(字节运算)或操作数为-32768(字运算)

OF=0 当求补运算的操作数不为-128(字节)或-32768(字)时


三、乘法指令


20、无符号乘法指令 NUL (unsigned multiple)

有符号乘法指令 IMUL(signed muliple)


指令的汇编格式:NUL src

IMUL src

指令的基本功能:(AX)<-(AL)*(src)

(DX,AX)<-(AX)*(src)

指令支持的寻址方式:src可以使用除立即数方式以外的任一种寻址方式。

指令对标志位的影响:乘法指令只影响标志位CF和OF,其他条件码位无定义。

MUL指令的条件码设置为:

CF OF=0 0 乘积的高一半为0(字节操作的(AH)或字操作的(DX))

CF OF=1 1 乘积的高一半不为0

IMUL指令的条件码设置为:

CF OF=0 0 乘积的高一半为低一半的符号扩展.

CF OF=1 1 其他情况

指令的特殊要求:MUL和IMUL指令的区别仅在于操作数是无符号还是带符号数,它们的共同点是,指令中只给出源操作数src,目的操作数是隐含的,它只能是累加器(字运算为AX,字节运算为AL)。隐含的乘积寄存器是AX或DX(高位)和AX(低位)。



四、符号扩展指令


21、节扩展为字 CBW (convert byte to word)


指令的汇编格式:CBW

指令的基本功能:(AH)=00H 当(AL)的最高有效位为0时

(AH)=FFH 当(AL)的最高有效位为1时

指令对标志位的影响:不影响标志位

指令的特殊要求:这是条无操作数的指令,进行符号扩展的操作数必须存放在AL寄存器或AX寄存器中。


22、字扩展为双字 CWD (convert word to double word)


指令的汇编格式:CWD

指令的基本功能:(DX)=0000H 当(AX)的最高有效位为0时

(DX)=FFFFH 当(AX)的最高有效位为1时

指令对标志位的影响:不影响标志位

指令的特殊要求:这是条无操作数的指令,进行符号扩展的操作数必须存放在AL寄存器或AX寄存器中。


五、除法指令


23、无符号数除法 DIV (unsigned divide)

带符号数除法 IDIV (singed divide)


指令的汇编格式:DIV src

IDIV src

指令的基本功能:字操作

(AL)<-(AX)/src的商

(AH)<-(AX)/src的余数

字节操作

(AX)<-(DX,AX)/src的商

(DX)<-(DX,AX)/src的余数

指令支持的寻址方式:src作为除数,可用除立即数以外的任一种寻址方式来取得。

指令对标志位的影响:不影响条件码。

指令的特殊要求:除法指令要求字操作时,被除数必须为32位,除数是16位,商和余数是16位的;

 字节操作时,被除数必须为16位,除数是8位,得到的商和余数是8位的。


六、十进制调整指令


[逻辑指令]


一、逻辑运算


24、逻辑与 AND (logic and)


指令的汇编格式:AND dst,src

指令的基本功能:(dst)<-(dst)与(src)

指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。

指令对标志位的影响:指令执行后 CF 和 OF 置零,AF无定义。

SF=1 指令执行后的结果为负数(符号位为1)

SF=0 指令执行后的结果为正数(符号位为0)

ZF=1 指令执行后的结果为零

ZF=0 指令执行后的结果不为零

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0


25、逻辑或 OR (logic or)


指令的汇编格式:OR dst,src

指令的基本功能:(dst)<-(dst)或(src)

指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,原操作数和目的操作数必须有一个寄存器寻址方式。

指令对标志位的影响:令执行后 CF 和 OF 置零,AF无定义。

SF=1 指令执行后的结果为负数(符号位为1)

SF=0 指令执行后的结果为正数(符号位为0)

ZF=1 指令执行后的结果为零

ZF=0 指令执行后的结果不为零

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0


26、逻辑非 NOT (logic not)


指令的汇编格式:NOT orc

指令的基本功能:(dst)<-(opr)

指令支持的寻址方式:除立即数寻址方式以外的其余寻址方式

指令对标志位的影响:对标志位无影响


27、异或 XOR (exclusice or)


指令的汇编格式:XOR dst,src

指令的基本功能:(dst)<-(dst)异或(src)

指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,原操作数和目的操作数必须有一个寄存器寻址方式。

指令对标志位的影响:令执行后 CF 和 OF 置零,AF无定义。

SF=1 指令执行后的结果为负数(符号位为1)

SF=0 指令执行后的结果为正数(符号位为0)

ZF=1 指令执行后的结果为零

ZF=0 指令执行后的结果不为零

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0


28、测试指令 TEST


指令的汇编格式:TEST opr1,opr2

指令的基本功能:(opr1)与(opr2)

指令支持的寻址方式:两个操作数不能同时为存储器寻址,即为除源操作数为立即数的情况外,源操作数和目的操作数必须有一个寄存器寻址方式。

指令对标志位的影响:令执行后 CF 和 OF 置零,AF无定义。

SF=1 指令执行后的结果为负数(符号位为1)

SF=0 指令执行后的结果为正数(符号位为0)

ZF=1 指令执行后的结果为零

ZF=0 指令执行后的结果不为零

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0


二、移位指令


29、逻辑左移 SHL (shift logical left)


指令的汇编格式:SHL dst,cnt

指令的基本功能:SHL指令向左逐位移动cnt次,每次逐位移动后,最低位用0来补充,最高位移入CF。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


30、逻辑右移 SHR (shift logical right)


指令的汇编格式:SHR dst,cnt

指令的基本功能:SHR指令向右逐位移动cnt次,每次逐位移动后,最高位用0来补充,最低位移入CF。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


31、算术左移 SAL (shift arithmetic left)


指令的汇编格式:SAL dst cnt

指令的基本功能:SAL指令向左逐位移动cnt次,每次逐位移动后,最低位用0来补充,最高位移入CF。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


32、算术右移 SAR (shift arithmetic right)


指令的汇编格式:SAR dst,cnt

指令的基本功能:SAR指令向右逐位移动cnt次,每次逐位移动后,最高位用符号位来补充,最低位移入CF。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


33、循环左移 ROL (rotate left)


指令的汇编格式:ROL dst,cnt

指令的基本功能:ROL 对由dst指定的寄存器或存储器操作数左移循环移动cnt所指定的次数,每左移一次,把最高位同时移入CF和操作数最低位。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


34、循环右移 ROR (rotate right)


指令的汇编格式:ROR dst,cnt

指令的基本功能:ROR 对由dst指定的寄存器或存储器操作数右移循环移动cnt所指定的次数,每右移一次,把最低位同时移入CF和操作数最高位。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt>1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

SF、ZF、PF根据移动后的结果设置。


35、带进位的循环左移 RCL (rotate left through carry)


指令的汇编格式:RCL dst,cnt

指令的基本功能:RCL 对由dst指定的寄存器或存储器操作数,连同进位标志CF左循环移动,m所指定的次数,每左移一次,把操作数的最高位移入CF,而CF中原有内容移入操作数的最低位。

指定支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值。

OF=1 当cnt=1时,移动后最高位的值未发生变化。

OF=0 当cnt=1时,移动后最高位的值发生变化。

SF、ZF、PF标志位不受影响。


36、带进位的循环右移 RCR (rotate right through carry)


指令的汇编格式:RCR dst,cnt

指令的基本功能:RCR 对由dst指定的寄存器或存储器操作数,连同进位标志CF右循环移动,m所指定的次数,每右移一次,把操作数的最高低位移入CF,而CF中原有内容移入操作数的最高位。

指令支持的寻址方式:目的操作数dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写入指令中,cnt〉1时,cnt必须放入CL寄存器中。

指令对标志位的影响:CF=移入的数值。

OF=1 当cnt=1时,操作数最高位的值未发生变化。

OF=0 当cnt=1时,操作数最高位的值发生变化。

SF、ZF、PF标志位不受影响。


[串处理指令]


一、设置方向标志指令


37、DF置零 CLD (clear direction flag)

DF置一 STD (set direction flag)


指令的汇编格式:CLD

STD

指令的基本功能:CLD DF=0

STD DF=1


二、串处理指令


38、串传送 MOVSB / MOVSW (move string byte/word)


指令的汇编格式:MOVSB

MOVSW

指令的基本功能:(ES:DI)<-(DS:SI)

(SI)<-(SI)+/-1(字节)或+/-2(字)

(DI)<-(DI)+/-1(字节)或+/-2(字)

指令对条件码的影响:不影响条件码。

指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。


39、存串 STOSB / STOSW (stroe from string byte/word)


指令的汇编格式:STOSB

STOSW

指令的基本功能:(ES:DI)<-(AL)或(AX)

(DI)<-(DI)+/-1(字节)或+/-2(字)

指令对条件码的影响:不影响条件码。

指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。


40、取串LODSB / LODSW (load from string byte/word)


指令的汇编格式:LODSB

LODSW

指令的基本功能:(AL)或(AX)<-(DS:SI)

(SI)<-(SI)+/-1(字节)或+/-2(字)

指令对条件码的影响:不影响条件码。

指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。


41、串比较 CMPSB / CMPSW (compare string byte/word)


指令的汇编格式:CMPSB

CMPSW

指令的基本功能:(DS:SI)-(ES:DI) 根据比较结果设置条件码

(SI)<-(SI)+/-1(字节)或+/-2(字)

(DI)<-(DI)+/-1(字节)或+/-2(字)

指令对条件码的影响:SF=1 减法结果为负数(符号位为1)

SF=0 减法结果为正数(符号位为0)

ZF=1 减法结果为零

ZF=0 减法结果不为零

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


42、串扫描 SCASB / SCASW (scan string byte / word)


指令的汇编格式:SCASB

SCASW

指令的基本功能:(AL)<-(ES:DI)或(AX)<-(ES:DI) 根据扫描比较的结果设置条件码。

(DI)<-(DI)+/-1(字节)或+/-2(字)

指令对条件码的影响:SF=1 结果为负数(符号位为1)

SF=0 结果为正数(符号位为0)

ZF=1 结果为零

ZF=0 结果不为零

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。


三、串重复前缀


43、重复执行串 REP


指令的汇编格式:REP (CX)=重复次数

指令的基本功能:① (CX)=0时,串指令执行完毕,否则执行② ~ ④

   ② (CX)←(CX)-1

   ③ 执行串指令(MOVS或STOS)

  ④ 重复执行①


44、相等/为零时重复执行串指令 REPE/REPZ


指令的汇编格式:REPE / REPZ (CX)=比较/扫描的次数

指令的基本功能:① (CX)=0或ZF=0时,结束执行串指令,否则继续② ~ ④

   ② (CX)←(CX)-1

   ③ 执行串指令(CMPS或SCAS)

   ④ 重复执行①


45、不等/不为零时重复执行串指令 REPNE / PEPNZ


指令的汇编格式:REPNE / PEPNZ (CX)=比较/扫描的次数

指令的基本功能:① (CX)=0或ZF=1,结束执行串指令,否则继续② ~ ④

   ② (CX)←(CX)-1

   ③ 执行串指令(CMPS或SCAS)

   ④ 重复执行①


[控制转移指令]


一、无条件转移指令


46、短转移 JMP SHORT label (short jump)


指令的汇编格式:JMP SHORT label

指令的基本功能:(IP)<-当前(IP)+8位位移量 8位位移量是汇编程序在汇编源程序时,根据目标地址和当前IP之间的距离自动生成的。

指令对条件码的影响:对标志位无影响。


47、近转移 JMP NEAR PTR label (near jump)


指令的汇编格式:直接转移 JMP label (direct jump)

寄存器间接转移 JMP reg (register indirect jump)

存储器间接转移 JMP WORD PTR OPR (memory indirect jump)

指令的基本功能:JMP label (IP) <- OFFSET label = (IP)当前+16位位移量

JMP reg (IP) <- (reg)

JMP WORD PTR OPR (IP) <- (PA+1,PA)

指令支持的寻址方式:指令中的转向地址可以是直接寻址方式、寄存器寻址方式、寄存器间接寻址方式和存储器寻址方式。

指令对条件码的影响:对标志位无影响。


48、远转移 JMP FAR PTR label (for jump)


指令的汇编格式:JMP FAR PTR label

指令的基本功能:(IP)<-label的段内偏移地址

(CS)<-label所在段的段地址

指令支持的寻址方式:远转移的目的地址可以使用除立即寻址方式外的任何寻址方式来表示。

指令对条件码的影响:对标志位无影响。


二、条件转移指令


指令的汇编格式及功能

根据条件码的值转移:

49、JZ(JE) OPR ZF=1

50、JNZ(JNE) OPR ZF=0

51、JS OPR SF=1

52、JNS OPR SF=0

53、JO OPR OF=1

54、JNO OPR OF=0

55、JP OPR PF=1

56、JNP OPR PF=0

57、JC OPR CF=1

58、JNC OPR CF=0


比较两个无符号数,根据比较的结果转移

59、JB(JNAE,JC) OPR CF=1 被减数小于减数则转移

60、JNB(JAE,JNC) OPR CF=0 被减数大于或等于减数则转移

61、JBE(JNA) OPR CF或ZF=1 被减数小于或等于减数则转移

62、JNBE(JA) OPR CF或ZF=0 被减数大于减数则转移


比较两个带符号数,根据比较结果转移

63、JL/JNGE OPR SF异或OF=1 被减数小于减数则转移

64、JNL/JGE SF异或OF=0 被减数不小于减数则转移

65、JLE/JNE (SF异或OF)与ZF=1 被减数不大于减数则转移

66、JNLE/JG (SF异或OF)与ZF=0 被减数大于减数则转移


根据CX寄存器的值转移

67、JCXZ (CX)=0 CX内容为零 则转移


指令的特殊要求:所有条件转移指令都是短转移指令,转移的目标地址必须在当前IP地址的-128至+127字节范围之内,因此条件转移指令是2字节指令。


三、循环指令


68、循环 LOOP (loop)

指令的汇编格式:LOOP label

指令的基本功能:① (CX)←(CX)-1

        ② 若(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。

指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。


69、为零/相等时循环 LOOPZ/LOOPE (loop while nonzero or equal)

指令的汇编格式:LOOPNZ/LOOPNE label

指令的基本功能:① (CX)←(CX)-1

        ② 若ZF=1且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。

指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。


70、不为零/不相等时循环 LOOPNZ/LOOPNE (loop while nonzero or not equal)

指令的汇编格式:LOOPNZ/LOOPNE label

指令的基本功能:① (CX)←(CX)-1

        ② 若ZF=0且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。

指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。


四、子程序调用


71、段内直接近调用 CALL SUBROUT

指令的基本功能:(SP)<-(SP)-2

((SP)+1,(sp))<-(IP)

(IP)<-(IP)+16位位移量

段内间接近调用 CALL DESTIN

指令的基本功能:(SP)<-(SP)-2

((SP)+1,(SP))<-(IP)

(IP)<-(EA)


72、段间直接调用 CALL FAR PTR SUBROUT

指令的基本功能:(SP)<-(SP)-2,((SP))<-(CS)当前

(SP)<-(SP)-2,((SP))<-(IP)当前

(IP)<-偏移地址(在指令的第2、3个字节)

(CS)<-段地址(在指令的第4、5个字节)


五、返回指令


73、段内返回(近返回) RET

指令的基本功能:(IP)<-((SP)+1,(SP))

(SP)<-(SP)+2


段间返回(远返回) RET

指令的基本功能:(IP)<-((SP)),(SP)<-(SP)+2

(CS)<-((SP)),(SP)<-(SP)+2


带立即数返回 RET N

执行操作:① 返回地址出栈(操作同段内或段间返回)

     ② 修改堆栈指针:(SP) ← (SP)+N


六、中断及中断返回指令


74、INT n 中断指令(interrupt),n为中断类型号

  执行操作:① 入栈保存FLAGS:(SP) ← (SP)-2,((SP)) ← (FLAGS)

       ② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)

                  (SP) ← (SP)-2,((SP)) ← (IP)

       ③ 转中断处理程序:(IP) ← (n×4)

                 (CS) ← (n×4+2)


75、IRET 中断返回指令(return from interrupt)

  执行操作:① 返回地址出栈:(IP) ← ((SP)),(SP) ← (SP)+2

                (CS) ← ((SP)),(SP) ← (SP)+2

       ② FLAGS出栈:(FLAGS) ← ((SP)),(SP) ← (SP)+2


76、INTO 溢出则中断(中断类型为4)

  执行操作:若OF=1(有溢出),则:

       ① 入栈保存FLAGS:(SP) ← (SP)-2,((SP)) ← (FLAGS)

       ② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)

                  (SP) ← (SP)-2,((SP)) ← (IP)

       ③ 转中断处理程序:(IP) ← (4×4)= (10H)

                 (CS) ← (4×4+2)= (12H)



完.

汇编笔记2

逻辑指令包括逻辑运算指令和移位指令。逻辑运算指令可对操作数执行逻辑运算,移位指令执行对操作数左移或右移若干位的功能。

 ⑴ 逻辑运算指令          ⑵ 移位指令

   AND     逻辑与          SAL     算术左移

   OR      逻辑或          SHR     逻辑右移

   OT      逻辑非          SAR     算术右移

   XOR     异或           ROL    循环左移

   TEST     测试           ROR    循环右移

                     RCL    带进位循环左移

                     RCR    带进位循环右移

 移位指令包括逻辑移位指令、算术移位指令、循环移位指令和带进位循环移位指令。指令中的目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可直接写在指令中;cnt>1时,cnt必须放入CL寄存器。

 

 SHL dst,cnt ; 逻辑左移(shift logical left)

 
执行操作:


 SHR dst,cnt ; 逻辑右移(shift logical right)

 执行操作:


 SAL dst,cnt ; 算术左移(shift arithmetic left)

 执行操作:


 SAR dst,cnt ; 算术右移(shift arithmetic right)

 
执行操作:


  SHL和SAL指令向左移动的操作是相同的,在每次逐位移动后,最低位用0来补充,最高位移入CF。SHR与SHL移动的方向相反,每次向右移动后,最高位用0来补充,最低位移入CF。SAR在每次右移都用符号位的值补充最高位,最低位仍然是移入CF。


  由此可以看出,算术移位适于带符号数的移位处理。我们知道,一个数左移n位相当于乘以2n,右移n位相当于除以2n, 所以,当一个带符号数需要乘(或除)2n时,可使用算术移位指令SAL(或SAR)。当一个无符号数需要乘(或除)2n时,可使用逻辑移位指令SHL(或SHR)。使用移位指令将一个数扩大或缩小2n倍,比使用乘法或除法指令的速度快。


  移位指令的条件码设置:

  CF= 移入的数值

  OF=1 当cnt=1时,移动后最高位的值发生变化

  OF=0 当cnt=1时,移动后最高位的值未发生变化

  SF、ZF、PF根据移动后的结果设置


 ROL dst,cnt ; 循环左移(rotate left)

 执行操作:

 


 ROR dst,cnt ; 循环右移(rotate right)

 
执行操作:

 


 RCL dst,cnt ; 带进位循环左移(rotate left through carry) 

 执行操作:

 


 RCR dst,cnt ; 带进位循环右移(rotate right through carry)

 执行操作:

 


  这组指令完成位循环移位的操作,ROL和ROR是简单的位循环指令,RCL和RCR是连同CF位一起循环移位的指令。它们左右移动的方法以及移位次数的设置与移位指令类似。


  循环移位指令执行后,CF和OF的设置方法与移位指令相同;SF、ZF和PF标志位不受影响。

;SF、ZF和PF标志位不受影响。

串处理指令

       ⑴ 串处理指令

        MOVSB / MOVSW   串传送

        STOSB / STOSW   存串

        LODSB / LODSW   取串

        CMPSB / CMPSW   串比较

        SCASB / SCASW   串扫描


       ⑵ 串重复前缀

        REP        重复串操作

        REPE / REPZ    相等/为零时重复

        REPNE / REPNZ   不等/不为零时重复


       ⑶ 设置方向标志

        CLD        使DF=0

        STD        使DF=1

设置方向标志:DF=0..串的传送从低地址向高地址传送.如果DF=1串的传送从高地址向低地址传送

串处理指令处理存放在存储器中的字节串或字串,串处理的方向由方向标志位DF决定,串处理指令之前可加重复前缀,在执行串处理指令时,源串的指针SI和目的串的指针DI根据DF的指示自动增量(+1或+2)或自动减量(

汇编过程中遇到的困难…….原码..反码..补码..

数值在计算机中表示形式为机器数,计算机只能识别01,使用的是二进制,而在日常生活中人们使用的是十进制,”正如亚里士多德早就指出的那样,今天十进制的广泛采用,只不过我们绝大多数人生来具有10个手指头这个解剖学事实的结果.尽管在历史上手指计数(5,10进制)的实践要比二或三进制计数出现的晚.”(摘自<<数学发展史>>有空大家可以看看哦~,很有意思的).为了能方便的与二进制转换,就使用了十六进制(2 4)和八进制(23).下面进入正题.

数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,原码能表示数值的范围为

(-127~-0 +0~127)256.

有了数值的表示方法就可以对数进行算术运算.但是很快就发现用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题,如下: 假设字长为8bits

( 1 ) 10 ( 1 )10 = ( 1 )10+ ( -1 )10= ( 0 )10

(00000001) + (10000001) = (10000010)= ( -2 ) 显然不正确.

因为在两个整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负数身上,对除符号位外的其余各位逐位取反就产生了反码.反码的取值空间和原码相同且一一对应. 下面是反码的减法运算:

( 1 )10 ( 1 ) 10= ( 1 ) 10+ ( -1 ) 10= ( 0 )10

(00000001) + (11111110)= (11111111) = ( -0 ) 有问题.

( 1 )10 ( 2)10= ( 1 )10+ ( -2 )10= ( -1 )10

(00000001) + (11111101)= (11111110) = ( -1 ) 正确

问题出现在(+0)(-0),在人们的计算概念中零是没有正负之分的.(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大).

于是就引入了补码概念. 负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:

(-128~0~127)256.

注意:(-128)没有相对应的原码和反码, (-128) = (10000000) 补码的加减运算如下:

( 1 ) 10 ( 1 ) 10= ( 1 )10+ ( -1 )10= ( 0 )10

(00000001) + (11111111)= (00000000) = ( 0 ) 正确

( 1 ) 10 ( 2) 10= ( 1 )10+ ( -2 )10= ( -1 )10

(00000001) + (11111110) = (11111111)= ( -1 ) 正确

   所以补码的设计目的是:

     ⑴使符号位能与有效值部分一起参加运算,从而简化运算规则.

⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计

所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、C等其他高级语言中使用的都是原码。看了上面这些大家应该对原码、反码、补码有了新的认识了吧!

汇编笔记1

发现汇编非常重要….在学校没有在家接触电脑的时候多….赶快把汇编视频看一遍吧..挺有用的…毕竟是接触到了计算机底层的东西了….做点笔记..写下来..也算是一种收获吧!

指令系统.

通用数据传送指令

传送指令:mov DST,SRC

几点注意:1.DST不能为CS

                2.DST,SRC不能同时为段寄存器

               3.DST,SRC不有同时为存储器寻址

               4.DST不能为立即数

                5.立即数不能送段寄存器.

进栈指令:push SRC

出栈指令:POP DST

堆栈:”先进后出”的存储区,存在于堆栈段,SP在任何时候都指tmk sgt sdm .

几点注意:1.堆栈操作必须以字为单位

                2.不能影响标志位

                3.不能用立即寻址方式    push 1234H (错误)

               4.DST不能是CS             pop CS (错误)

交换指令:xchg opr1,opr2

几点注意:1.不能影响标志位

         2.不允许使用段寄存器

例:xchg BX,[BP+SI]

    xchg AL,BH

累加器专用传送指令(只限使用AX或AL)

输入指令(I/O→CPU)

长格式:IN AL,PORT (字节)

    IN AX,PORT (字)

执行操作:(AL)←(PORT)   (字节)

                (AX)←(PORT+1,PORT)   (字)

短格式:IN AL,DX (字节)

                IN AX,DX (字)

执行操作:(AL)←((DX))   (字节)

                (AX)←((DX)+1,(DX))   (字)

输出指令(CPU→I/O)

与IN指令相反

几点注意:1.不影响标志位.

     2.前256个端口号00H~FFH可直接在指令中指定(长格式)

     3.如果端口号>=256,端口号→DX(短格式)

例:  IN AX,28H                  ;MOV DX,28H

                                             ;IN    AX,DX

             MOV DATA_WORD,AX

例:  Mov DX,3FCH

             IN AX,DX

例:       OUT 5,AL

换码指令:XLAT或 XLAT OPR

执行操作:(AL)←((Bx)+(AL))

注意:1.不影响标志位

   2.字节表格(长度不超过256)  首地址→(BX)

   3.需转换代码→(AL)

地址传送指令

有效地址送寄存器指令: LEA REG,SRC

执行操作:       (REG)←SRC

指针送寄存器和DS指令:LDS REG,SRC

执行操作:                       (REG)←(SRC)

                                         (DS)←(SRC+2)

4个相继字节→寄存器(通常是SI),DS

指针送寄存器和ES指令:LES REG,SRC

执行操作:                       (REG)←(SRC)

                                         (ES)←(SRC+2)

4个相继字节→寄存器(通常是DI),ES

例:TABLE   (DS):1000H由低到高依次是 40H,00H,00H,30H

MOV BX,TABLE                 BX=0040H

MOV BX,OFFSET TABLE BX=1000H

LEA BX,TABLE                 BX=1000H

LDS BX,TABLE                 BX=0040H

                                          DS=3000H

LES BX,TABLE                 BX=0040H

                                           ES=3000H

几点注意:1.不影响标志位

                  2.REG不能是段寄存器

                  3.SRC必须为存储器寻址方式

类型转换指令

CBW           AL→AX

执行操作:若(AL)的最高有效位为0,则(AH)=00H

               若(AL)的最高有效位为1,则(AH)=0FFH

CWD          AX→(DX,AX)

执行操作:若(AX)的最高有效位为0,则(DX)=0000H

               若(AX)的最高有效位为1,则(DX)=0FFFFH

例:(AX)=0BA45H

   CBW        ;(AX)=0045H

   CWD        ;(DX)=0FFFFH (AX)=0BA45H

几点注意:1.无操作数指令

                2.隐含对AL或对AX进行符号扩展

               3.不影响条件标志位

算术指令

加法指令: ADD DST,SRC

执行操作:(DST)←(SRC)+(DST)

带进位加法指令:ADC DST,SRC

执行操作: (DST)←(SRC)+(DST)+CF

加1指令:   INC OPR

执行操作: (OPR)←(OPR)+1

几点注意:除INC指令不影响CF标志位外,均对条件标志位有影响。

加法指令对条件标志位(CF/OF/ZF/SF)的影响

SF=1结果为负   ZF=1结果为0

CF=1和的最高有效位有向高位的进位

OF=1两个操作数符号相同,而结果符号与之相反以

CF位表示无符号数相加的溢出

OF位表示带符号数相加的溢出

例:双精度数的加法

(DX)=0002H     (AX)=0F365H

(BX)=0005H      (CX)=0E024H

指令序列:(1)ADD AX,CX

                   ( 2 ) ADC DX,BX

(1)执行后 (AX)=0D389H          CF=1    OF=0     SF=1   ZF=0

(2 )执行后 (DX)=0D389H          CF=0    OF=0     SF=0   ZF=0

减法指令

减法指令: SUB DST,SRC

执行操作:(DST)←(DST)-(SRC)

带借位减法指令:SUB DST,SRC

执行操作: (DST)←(SRC)-(DST)-CF

减1指令:DEC OPR

执行操作:(OPR)←(OPR)-1

求补指令:NEG OPR

执行操作:(OPR)←-(OPR)

比较指令:CMP OPR1,OPR2

执行操作:(OPR1)-(OPR2)

注意:除DEC指令不影响CF标志位外,均对条件标志位有影响。

NEG指令对CF/OF的影响:

CF=0 操作数为0   否则CF=1

OF=1 操作数为-128 (字节运算)或操作数为-32768(字运算) 否则为0

堆栈变化….

汇编初学者比较头痛的一个问题

////////////////////////////////////////////////////////////////////

比如 我们有这样一个C函数

#include<stdio.h>

long test(int a,int b)

{

     a = a + 1;

     b = b + 100;

     return a + b;

}

void main()

{  

   printf(“%d”,test(1000,2000));

}


写成32位汇编就是这样

;//////////////////////////////////////////////////////////////////////////////////////////////////////

.386

.model flat,stdcall            ;这里我们用stdcall 就是函数参数 压栈的时候从最后一个开始压,和被调用函数负责清栈

option casemap:none             ;区分大小写


includelib msvcrt.lib           ;这里是引入类库 相当于 #include<stdio.h>了       

printf   PROTO C:DWORD,:VARARG   ;这个就是声明一下我们要用的函数头,到时候 汇编程序会自动到msvcrt.lib里面找的了

                                 ;:VARARG 表后面的参数不确定 因为C就是这样的printf(const char *, …);

                                ;这样的函数要注意 不是被调用函数负责清栈 因为它本身不知道有多少个参数

                                ;而是有调用者负责清栈   下面会详细说明

.data

szTextFmt   BYTE ‘%d’,0         ;这个是用来类型转换的,跟C的一样,字符用字节类型

a           dword 1000          ;假设

b           dword 2000          ;处理数值都用双字 没有int 跟long 的区别


;/////////////////////////////////////////////////////////////////////////////////////////

.code


_test proc ;A:DWORD,B:DWORD

       push ebp

       mov   ebp,esp

       mov   eax,dword ptr ss:[ebp+8]

       add   eax,1

       mov   edx,dword ptr ss:[ebp+0Ch]

       add   edx,100

       add   eax,edx

       pop   ebp      

       retn 8

_test endp


_main proc

       push dword ptr ds:b        ;反汇编我们看到的b就不是b了而是一个[*****]数字 dword ptr 就是我们在ds(数据段)把[*****]

                                 ;开始的一个双字长数值取出来

       push dword ptr ds:a        ;跟她对应的还有 byte ptr ****就是取一个字节出来 比如这样 mov   al,byte ptr ds:szTextFmt

                                 ;就把 % 取出来 而不包括 d

       call _test                  

       push eax                   ;假设push eax的地址是×××××

       push offset szTextFmt

       call printf

       add   esp,8

       ret             

_main endp

end   _main


;////////////////////////////////////////////////////////////// 下面介绍堆栈的变化

首先要明白的是 操作堆栈段 ss 只能用 esp或ebp寄存器 其他的寄存器eax ebx edx等都不能够用 而 esp永远指向堆栈栈顶 ebp用来 在堆栈段


里面寻址

push 指令是压栈 ESP=ESP-4

pop   指令是出栈 ESP=ESP+4

我们假设main函数一开始堆栈定是 ESP=400

push dword ptr ds:b                  ;ESP-4=396 ->里面的值就是 2000 就是b的数值

push dword ptr ds:a                  ;ESP-4=392 ->里面的值就是 1000 就是a的数值

call test                            ;ESP-4=388->里面的数值是什么?这个太重要了 就是我们用来找游戏函数的原理所在。

                                                  里面的数值就是call test 指令下一条指令的地址->即push eax的地址×××××


到了test函数里面


push ebp                            ;ESP-4=384->里面保存了当前ebp的值 而不是把ebp清零

mov   ebp,esp                        ;这里ESP=384就没变化了,但是 ebp=esp=384,为什么要这样做呢 因为我们要用ebp到堆栈里面找参数

mov   eax,dword ptr ss:[ebp+8]       ;反汇编是这样的 想想为什么a就是[ebp+8]呢

                                    ;我们往上看看堆栈里地址392处就保存着a的值 这里ebp=384 加上8正好就是392了

                                    ;这样就把传递过来的1000拿了出来eax=1000

add   eax,1                          ;相当于 a+1了 eax=1001

mov   edx,dword ptr ss:[ebp+0Ch]     ; 0Ch=12 一样道理这里指向堆栈的地址是384+12=396 就是2000了 edx=2000

add   edx,100                        ;相当于 b+100 edx=2100

add   eax,edx                        ;eax=eax+edx=1001+2100=3101 这里eax已经保存了最终的结果了

                                    ;因为win32汇编一般用eax返回结果 所以如果最终结果不是在eax里面的话 还要把它放到eax

                                    ;比如假设我的结果保存在变量nRet里面 最后还是要这样 mov eax,dword ptr nRet

pop   ebp                            ;ESP=384+4=388 而保存在栈顶384的值 保存到 ebp中 即恢复ebp原来的值                       

                                    ;因为一开始我们就把ebp的值压栈了,mov ebp,esp已经改变了ebp的值,这里恢复就是保证了堆栈平衡

retn   8                             ;ESP+8->396 这里retn是由系统调用的 我们不用管 系统会自动把EIP指针指向 原来的call的下一条指令

                                    ;由于是系统自动恢复了call那里的压栈所以 真正返回到的时候ESP+4就是恢复了call压栈的堆栈

                                    ;到了这个时候 ESP=400 就是函数调用开始的堆栈,就是说函数调用前跟函数调用后的堆栈是一样的

                                    ;这就是堆栈平衡

由于我们用stdcall上面retn 8就是被调用者负责恢复堆栈的意思了,函数test是被调用者,所以负责把堆栈加8,call 那里是系统自动恢复的


push eax                 ;ESP-4=396->里面保存了eax的值3101

                         ;上面已经看到了eax保存着返回值,我们要把它传给printf也是通过堆栈传递       

push offset szTextFmt    ;ESP-4=392->里面保存了szTextFmt的地址 也就是C里面的指针 实际上没有什么把字符串传递的,我们传的都是地址

                         ;无论是在汇编或C 所以在汇编里没有什么字符串类型 用最多的就是DWORD。嘿嘿游戏里面传递参数 简单多了

call printf              ;ESP-4=388->里面保存了下一条指令的地址

add   esp,8               ;ESP+8=400 恢复了调用printf前的堆栈状态

                         ;上面说了由于printf后面参数是:VARARG 这样的类型是有调用者恢复堆栈的 所以printf里面没有retn 8之类的指令

                         ;这是由调用者负责清栈 main是调用者 所以下面一句就是 add esp,8 把堆栈恢复到调用printf之前

                         ;而call printf那里的压栈 是由系统做的 恢复的工作也是系统完成 我们不用理 只是知道里面保存是返回地址就够  


                       ;了

ret                      ;main 函数返回 其他的事情是系统自动搞定 我们不用理 任务完成

解密入门….必备基础知识

前言


很多人都想学习解密,这东西刚入门时会让人沉迷进去,可以饭不吃、觉不睡。出现这种现像,也许是解密满足了人们的猎奇心里吧。但掌握这方面技术,对自身的提高确实有好处。可以通过跟踪软件,提高自己的调试技能,并且能了解他人程序思路,使自己写出更好的程序。研究解密技术有助于掌握一些系统底层知识,系统底层知识绝对是构造起大型软件的坚实基础。许多程序发展,都经历了这一锻炼过程的。 而大多数人可能认为解密是一门高深的学问。造成这种原因是以前这方面的技术资料缺乏,从而将“解密”这一技能“神”化了。初学者一般不知从何下手,由于没方向,花费了大量时间和精力,走了不少弯路。这里就给对这方面感兴趣的读者指明一个方向。


讨论前,先了解一下计算机中的程序。高级语言编写的程序,会编译成机器语言在CPU中执行,如Visual C++等。由于机器语言与汇编语言是一一对应的,因此就可将机器语言转化成汇编语言,这个过程称之为反汇编。而汇编语言可能读性是比较好的,这样就可分析程序流程,解析其功能了,这个过程就是解密(俗称破解)。也就是说,解密的基础是建立在汇编语言级别上的,因此想涉足这一领域的朋友,汇编语言一定得学好。汇编语言是大学计算机的必修课,这方面的书籍品种很多,虽然大多书本是以DOS汇编为讲解平台,但对理解汇编指令功能是没影响的。

建议:在学汇编前,最好先掌握一门高级语言编程,推荐是C语言,这样再学汇编应容易些

http://bbs.pediy.com/upload/bbs/faq/prg8086.jpg


汇编教学资源:



中山大学的教程,学习时一天看一级,一级看2-3次为好,并随时做好笔记。一月下来就会有效果的。学完后可以到

http://www.315safe.com/download/SmallClass.asp?BigClassid=92&SmallClassid=134&page=2 再巩固下汇编。


等汇编学好了,此时一般的破解文章己能看懂了,但为了水平提高的更快些,建议再掌握Win32编程。Win32程序设计就是API方式的Windows编程,学习Windows API将使您更深入地了解Windows工作方式。此类书籍有Charles Petzold著的《Windows程序设计》(以VC来讲解)。另一本是罗云彬著的《Windows环境下32位汇编语言程序设计》,它以MASM汇编为讲解平台。

http://bbs.pediy.com/upload/bbs/faq/Petzold.jpg




有了上面这些基础,你就能看懂论坛中的一些文章了,也能看懂《 加密与解密(第二版) 》这本书了。
http://bbs.pediy.com/upload/bbs/faq/jm2.gif


学习解密其实很累的,需花费大量的时间,而且经常会碰壁,三五天毫无进展是极为平常的事情。这时你可能有点想退却,其实你不要着急,只要你认真学习,成功就在眼前。没有人是生来就什么都会的,如果你有问题,就大胆的去问你周围的人。学解密的秘诀就是勤奋+执着!记住并能做到这两点,你会变得很优秀的。


等你解密入门后,建议再看看Matt Pietrek、Jeffrey Ritcher等大师的专著,这些书是每个程序员都应该阅读的:《Windows 95 System Programming Secrets》(中文译名《Windows 95 系靳程式设计大?秘》),《windows高级编程指南》,《Windows2000编程技术内幕》,《Win32系统编程

在汇编语言中…”[]”的用法

文者:FTBirthday

内容:举例说明在汇编语言中,”[]”的用法

“[]”的用法在”常见问题”已经有所说明,引用如下:

1、push dword ptr [024c1100] 压栈024c1100值的双字

2、cmp eax,[ebp+14] eax-ebp+14的有效值,不保留值,主要看标志位

3、cmp byte ptr [eax],46 字节型eax-46,看标志位

4、lea eax,[edx-02] 把edx-02的有效值(一个地址值)给eax

5、mov ecx,[edx+08] edx+8值作为地址,此地址所指向的值给ecx

我再补充几例我遇到的情况,参考了一些资料,以及我个人的理解.

——————————————————————————-

mov指令中用到”[]”

1–mov [edi], eax —-把eax的值(dword)赋给位于内存地址edi处的值

2–mov [bp-02], dx —把dx的值(word)赋给位于内存地址bp-02处的值

3–mov esi,[BP+14] —把位于内存地址BP+14的dword大小的值移入esi寄存器

4–mov eax, dword ptr [ebp-04]—把位于内存地址ebp-04的dword大小的值移入eax寄存器

5–mov eax, dword ptr[0000003Ah]–把位于内存地址3A的dword大小的值放入eax寄存器

6–mov cl, byte ptr [34h]–把位于内存地址34的byte大小的值放入cl寄存器

7–mov dx, word ptr [3Eh]–把位于内存地址3E的word大小的值放入dx寄存器

8–mov eax,[00403045h] –从内存地址403045读取一个32位的值

9–mov al, byte ptr [eax+ecx]–把位于内存地址eax+ecx的byte大小的值放入al寄存器

综括号”[]”用来从括号间的内存地址处取值,没有括号就只是这个值,寄存器和内存地址也可以.

10–mov cx,[eax]–把位于内存地址eax的word大小的值移入cx寄存器

在mov cx, [eax]中,处理器会先查看eax装有什么值(=内存地址),然后在那个内存地址中有什么值,并把这个word(16位,因为目标-cx-是个16位寄存器)移入cx。

——————————————————————————-

cmp指令中用到”[]”

1–cmp dword ptr [ebp-04], 00000007–把位于内存地址ebp-04的dword大小的值与00000007比较

2–cmp byte ptr [si], 00 –把位于内存地址si的byte大小的值与00比较

——————————————————————————-

lea指令中用到”[]”

1–lea di, [bp-22] —-把bp-22的有效值(=内存地址)给di

——————————————————————————-

test指令中用到”[]”

1–test byte ptr [bx+08FD]

–将位于内存地址bx+08FD处的byte大小的值逻辑与,判断运算结果是否为00

理解上难免有偏差,请指正!


标 题:其实”[]”相当于指针,里面的内容是地址而不是数值,即使里面放的是寄存器也一样。  
发信人:qqj1228
详细信息:

基本上有以下几种情况:

1、”[]”内放立即数

mov eax,dword ptr [00403000h]

即把内存地址为403000的双字数据放入eax,为直接寻址。

2、”[]”内放寄存器

mov eax,dword ptr [ebx]

即把ebx中的地址所指的内容放入eax中,为寄存器间接寻址。

mov eax,dword ptr [eax+edi]

即把eax中的数值加上edi中的数值所的结果作为内存地址,其指向的内容放入eax中,等价于mov eax,dword ptr [eax][edi],也为寄存器间接寻址。

3、”[]”内放寄存器加立即数

mov eax,dword ptr [ebx+0ch]

即把ebx加0ch的结果作为内存地址,其指向的内容放入eax中,为寄存器相对寻址。

同样可等价于mov eax,dword ptr 0ch[ebx]。

4、”[]”内放寄存器乘以立即数

mov eax,dword ptr [edi*4]

即把edi内的地址乘四所得的新地址指向的内容放入eax中,为寄存器比例寻址。

以上是我的理解,如有错误之处还望高手批评指正。


标 题:to FTB: 
发信人:lianzi2000
详细信息:

to FTB:
你说的不太准确, 在[]内的东东不管是立即数还是寄存器还是表达式, 都相当于高级语言中的变量, 也就是一个地址. 真正的操作数是该地址上存放的内容. 例如:

cmp byte ptr [eax],46

并不是拿eax中的值和46比较, 而是用由DS:[eax]指明的内存地址上存放的一个字节和46比较. 同样,push dword ptr [024c1100] 是把在内存地址 024c1100 处存放的双字压入堆栈,而不是把数字024c1100本身压入堆栈.

虽说[]内是地址,但说它是指针也不是很对. 高级语言中所谓指针是指该变量存放的内容是一个地址. 例如: 我们在内存地址00478030处存放一个字符’c’,假设在C中的说明是:

char my_char=’c';

于是变量my_char就对应于地址00478030, [00478030]是一个字符型变量,

mov al, [00478030]

就是把字符’c’存入AL中.

若又有说明

char *p_char;

这时, 变量p_char也对应另一个地址,假设为00478158. [00478158]才是一个指针变量. 没有赋值以前其存放内容是不确定的.若有:

p_char=&my_char;

这时, 在内存00478158存放的内容是00478030, 而在00478030处存放的才是字符’c’. 指针和变量名的关系就是如此.

详细请参考我写的汇编心得

一个比较特别的指令是lea, 意思是”装入有效地址”(Load Effective Address), 它的操作数就是地址,所以

lea eax,[edx-02]

就是把 edx 中的值减去2再送入eax, 而不是把由[edx-02]指明的内存地址上的值放到eax. 其结果是[eax]和[ebx-02]都表示同一个地址.

test和cmp的比较…..

看过破解教程,都知道test,cmp是比较关键,可是我一直不清楚它们究竟是怎么比较的,最后下决心找了很多资料,和大家一起把它们弄清楚.

首先看看:状态寄存器(即标志寄存器)

PSW(Program Flag)程序状态字(即标志)寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,

如下所示:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

        OF DF IF TF SF ZF   AF   PF   CF

条件码:

①OF(Overflow Flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配.

②SF(Sign Flag)符号标志,结果为负时置1,否则置0.

③ZF(Zero Flag)零标志,运算结果为0时置1,否则置0.

④CF(Carry Flag)进位标志,进位时置1,否则置0.注意:Carry标志中存放计算后最右的位.

⑤AF(Auxiliary carry Flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。

有进位时1,否则置0.

⑥PF(Parity Flag)奇偶标志.结果操作数中1的个数为偶数时置1,否则置0.

控制标志位:

⑦DF(Direction Flag)方向标志,在串处理指令中控制信息的方向。

⑧IF(Interrupt Flag)中断标志。

⑨TF(Trap Flag)陷井标志。



为举例方便说一下jnz和jz

测试条件

JZ ZF=1

JNZ ZF=0

即Jz=jump if zero (结果为0则设置ZF零标志为1,跳转)

Jnz=jump if not zero

好,接着来看test和cmp

*******************************************************************************

test属于逻辑运算指令

功能: 执行BIT与BIT之间的逻辑运算

测试(两操作数作与运算,仅修改标志位,不回送结果).

Test对两个参数(目标,源)执行AND逻辑操作,并根据结果设置标志寄存器,结果本身不会保存。EST AX,BX 与 AND AX,BX 命令有相同效果

语法: TEST r/m,r/m/data

影响标志: C,O,P,Z,S(其中C与O两个标志会被设为0)

运用举例:

1.Test用来测试一个位,例如寄存器:

test eax, 100b; b后缀意为二进制

jnz ******; 如果eax右数第三个位为1,jnz将会跳转

我是这样想的,jnz跳转的条件是ZF=0,ZF=0意味着ZF(零标志)没被置位,即逻辑与结果为1.

2.Test的一个非常普遍的用法是用来测试一方寄存器是否为空:

test ecx, ecx

jz somewhere

如果ecx为零,设置ZF零标志为1,Jz跳转

*******************************************************************************

CMP属于算术运算指令

功能: 比较两个值(寄存器,内存,直接数值)

语法: CMP r/m,r/m/data

标志位: C,P,A,Z,O

CMP比较.(两操作数作减法,仅修改标志位,不回送结果).

cmp实际上是只设置标志不保存结构的减法,并设置Z-flag(零标志).

零标志很像carry,也是内部标志寄存器的一位.

例如:

Cmp eax, 2; 如果eax-2=0即eax=2就设置零标志为1

Jz ****; 如果设置了零标志就跳转



*******************************************************************************

我得出的结论

test逻辑与运算结果为零,就把ZF(零标志)置1;

cmp 算术减法运算结果为零,就把ZF(零标志)置1.