汇编基础知识点整合
初学汇编,对汇编程序还比较陌生,我个人在解题时习惯先写出C语言代码,而后转换成汇编代码
工具
汇编器:masm6.15
调试器:OllyDBG
编辑器:Notepad++
集成开发环境:DEV-C++
以上是我汇编学习过程用到的工具
前言
我们为什么要学习汇编语言呢?
汇编语言能够帮助我们理解计算机系统,分析与优化代码,能够用来分析恶意程序等等,且对于我们学习其他语言、其他计算机相关知识均有所帮助。
如何才能学好汇编呢?
我认为无论学习什么语言,方法都是共通的:刚开始不会写没关系,多借鉴、甚至直接copy别人的代码,但一定要理解、一行行弄懂,不会就问!!不要拖,否则到后面问题越积越多,都没有信心了。平时一定要多自己动手打,理论上无法理解的知识点,就自己敲个代码,反复修改运行来使自己理解。同时,要有耐心,一个个bug慢慢找,慢慢改,不要急于求成。对于我们,bug又何尝不是一种财富呢。
相信自己,你可以的,奥里给!
80x86的程序可见寄存器
可分为三类:通用寄存器、段寄存器、专用寄存器。下面重点介绍下通用寄存器
通用寄存器
又可分为三类:数据寄存器、地址指针寄存器、变址寄存器
数据寄存器:
32位:EAX,EBX,ECX,EDX
16位:AX,BX,CX,DX
8位:AH,AL,BH,BL,CH,CL,DH(高8位),DL(低8位)
EAX:累加器(Accumulator),所有I/O指令均必须通过AX与接口传送信息
EBX:基址寄存器(Base),在间接寻址中用于存放基地址
ECX:计数寄存器(Count),用于存放循环次数
EDX:数据寄存器(Data),在间接寻址的I/O指令中存放I/O端口地址
地址指针寄存器:
32位:ESP,EBP
16位:SP,BP
ESP:堆栈指针寄存器,其内容为当前栈顶的偏移地址
EBP:基址指针寄存器,常用于访问内存时存放内存单元的偏移地址
变址寄存器:
32位:ESI,EDI
16位:SI,DI
ESI:源变址寄存器,存放源操作数的偏移地址
EDI:目标变址寄存器,存放目标操作数的偏移地址
存储器中每一个单元的地址可以用两种方法表示:
1.逻辑地址:其表达形式为“段地址:段内偏移地址”。
2.物理地址:CPU与存储器进行数据交换时在地址总线上提供的20位地址信息称为物理地址。
物理地址=段地址×10H+段内偏移量
存储器的操作完全基于物理地址。
堆栈,内存中一个按先进后出(FILO)方式操作的特殊区域,用于存放返回地址、过程参数或需要保护的数据。
汇编语言中不区分大小写
80x86的寻址方式
指令:控制计算机完成指定操作的命令,由操作码和操作数两部分组成。
操作码:处理器要执行哪种操作,不可缺少,用助记符表示
操作数:指令执行的参与者,通过地址指示
汇编指令:助记符形式的指令
指令系统:CPU所有指令及其使用规则的集合
立即数寻址
数据在指令代码中,用常量表示。
立即寻址只能用于源操作数,且源操作数长度与目的操作数长度相同。
例如:mov al,12h ;正确
mov 12h,al;错误
立即数的类型由对应的寄存器或变量类型决定
寄存器寻址
操作数放在寄存器中,源操作数与目的操作数字长要相同。
寄存器寻址方式简单快捷,最常使用。
直接寻址
指令中直接给出操作数的32位偏移地址
例如:mov ax,[2000H]
寄存器间接寻址
操作数的偏移地址放在寄存器中,操作数在存储器中
寄存器相对寻址
EA=基址或变址寄存器的内容加指令中指定的位移量
基址-变址寻址
操作数的偏移地址由一个基址寄存器的内容和一个变址寄存器的内容相加形成
基址-变址相对寻址
在基址-变址寻址的基础上加一个相对位移量。这种寻址方式通常用于二维数组的寻址。
80x86指令系统
数据传送指令
把数据从一个位置传送到另一个位置
-
mov dest,src ;目的操作数不能是立即数,EIP不能作为目的寄存器,源操作数与目的操作数类型要一致
(dest)<-(src),传送的是字节、字、双字 -
movsx 有符号扩展传送指令 源操作数可以是8位或16位,而目的操作数必须是16位或32位
两种格式:
movsx reg1,reg2
movsx reg,mem
例如:
movsx eax,cl;将cl寄存器中的8位数,符号扩展成32位数,送到eax寄存器 -
movzx 无符号扩展传送指令
两种格式同movsx
例如:
movzx dx,al;将al寄存器中的8位数,零扩展成16位数,送到dx寄存器 -
push 进栈指令
push src -
pop 出栈指令
pop srt -
pusha/pushad 所有寄存器进栈指令
32位通用寄存器依次进栈,进栈次序为:eax,ebx,ecx,edx,指令执行前的esp,ebp,esi,edi
指令执行后,(esp)<-(esp)-32 -
popa/popad 所有寄存器出栈指令
出栈次序与入栈次序相反,指令执行后(esp)<-(esp)+32,出栈的esp未存入esp寄存器 -
xchg 交换指令 交换两操作数的内容
要求两操作数中必须有一个在寄存器中,操作数不能为段寄存器和立即数,源操作数和目的操作数类型要一致
eg: xchg al,bh
地址传送指令
共六种,下面重点讲解有效地址传送寄存器指令 LEA(Load Effective Address)
LEA指令获得存储器操作数的有效地址,在LEA指令执行时计算地址,对任何寄存器寻址方式都可用
区别以下两条指令:
lea ebx,buffer;将符号地址为buffer的存储单元的偏移地址取到ebx中
mov ebx,buffer;将buffer存储单元中的内容取到ebx中
以下两条指令等效:
lea ebx,buffer
mov ebx,offset buffer;offset只能取静态的地址,常用于对存储器的直接寻址
算术运算指令
两种类型数据:无符号数、有符号数
CF标志可用来表示无符号数的进位,OF标志可用来表示有符号数的溢出
零标志ZF:运算结果为0,ZF=1,否则,ZF=0
符号标志SF:运算结果最高位为1,SF=1;否则,SF=0
奇偶标志PF:运算结果低8位中“1”的个数为偶数时,PF=1;否则,PF=0
加法指令:add 该指令对标志位都有影响
格式:add mem/reg,data
add mem/reg1,mem/reg2;不能同时是存储器
加1inc 该指令不影响CF标志
减法指令:sub 源操作数和目的操作数不能同时为存储器操作数,目的操作数不能是立即数
减1指令: dec
求补指令: neg 把操作数按位求反后末位加1,利用该指令可得到负数的绝对值
比较指令:cmp 两操作数相减,结果不送往目标操作数,根据结果设置条件标志位
cmp dest,src
若ZF=1,两数相等(jz/je)
若ZF=0,两数不相等(jnz/jne):
若比较的是两个无符号数,CF=0,则dest>src (ja),CF=1,则dest<src (jb)
若比较的是两个有符号数,若OF异或SF=0,dest>src(jg) ;OF异或SF=1,dest<src(jl)
乘法指令:无符号乘法指令 MUL
格式:mul src
操作:字节操作数 (ax)<–(al)*src
字操作数 (dx,ax)<–(ax)*src
双字操作数 (edx,eax)<–(eax)*src
除法指令:无符号除法指令div
格式:div src ;src不能为立即数
位操作类指令
串处理指令
- movs 串传送指令
三种格式:movsb(字节),movsw(字),movsd(双字)
将esi所指向的内存拷到目的地址edi中
rep movsb/movsw:将整块内存拷贝,ecx: movsb/movsw这条指令重复执行次数(一般为串长度)
模板:
lea esi,buffer
lea edi,str1
mov ecx,len1
cld ;esi,edi向前移动一位(std 向后移动)
rep movsb ;每次ecx-1,当ecx为0,重复终止 - 串重复操作指令rep(每次执行ecx都会-1,当ecx为0,重复终止)
重复指令:repe(相等时重复)/repz(为0时重复) :zf=0或ecx=0时终止
repne(不相等时重复)/repnz(不为0时重复) ;zf=1或ecx=0时终止 - 串扫描指令scasb(字节al)/scasw(字ax)/scasd(四个字节eax)
在目的串中找一个特定字节/字数据
edi存放待查找字符串,al存放待查找字节,ecx为字符串大小
模板:lea edi,buffer
mov al,’ ’
mov ecx,128
cld
repne scasb; rep为重复指令,每次执行ecx都会-1,这条语句意思:当ecx为0或者找到目标字节(zf=1)时重复终止
;注:最后ecx的值为目标字节在字符串中的第几位
scasb具体语义:al-edi,结果改变标志寄存器的值:若等于0,则zf=1,若不为0,则zf=0 - 串比较指令
((ESI))-((EDI)) 根据比较结果置条件标志位:相等ZF=1,不等ZF=0