汇编整理.docx
《汇编整理.docx》由会员分享,可在线阅读,更多相关《汇编整理.docx(39页珍藏版)》请在冰点文库上搜索。
汇编整理
第1章汇编语言基础知识
国内asm网站
罗云彬 <>
国内讨论破解
对应的论坛
国外破解
国外讨论32位汇编
国外讨论破解
1.1什么是汇编语言
1.1.1计算机语言的地位和作用
1.1.2计算机语言的分类
假如要编程计算1+1=?
,则可用BASIC、C、ASM、机器语言分别写出如下程序:
① BASIC程序
x=1
x=x+1
② C语言程序
int x;
x=1;
x++;
③ 汇编语言(AssemblyLanguage)程序
mov ax,1
add ax,1
④ 机器语言程序
→10111000
00000001
00000000
→00000101
00000001
00000000
汇编语言是对机器语言的符号化
IntelCPU电脑中,所以长度超过1个字节的值
都按照低字节在前,高字节在后的顺序存放到内存中。
例如有一个16位数=1011011011110000
高8位 低8位
现在要把它放到内存地址1000开始的单元中:
地址 值
1000 11110000
1001 10110110
Little-Endian表示法
1.1.3汇编语言 港台:
组合语言
英文名称:
AssemblyLanguage assemble组合
汇编语言是最接近机器语言的低级语言。
1.2为什么要学习汇编语言
1.2.1汇编语言的特点
汇编语言主要有三大特点:
控制强、代码短、速度快。
假定汇编编译软件安装在C:
\masm
该文件夹中包含以下文件:
masm.exe 编译器
link.exe 连接器
bin.exe
编辑器
汇编编译步骤:
1.用MASM编译(Microsoft)
主页下载该压缩包,解压缩后生成几个文件:
masm.exe link.exe bin.exe
假定解压缩到C:
\masm文件夹
现在已经编好了hello.asm源程序
(1)MASMhello; 编译hello.asm→hello.obj
(2)LINKhello; 连接hello.obj→hello.exe
(3)hello 运行
2.用TASM编译(Borland)
(1)TASM/zi/zdhello.asm 编译
(2)TLINK/vhello 连接
(3)hello 运行
(4)TDhello 用TurboDebugger调试
编译参数/zi/zd/v是为了用TD进行源程序级调试
MASM的具体步骤:
开始->运行->command 进入DOS方式
C:
转到C盘
cd\masm 进入c:
\masm文件夹
cd:
changedirectory改变目录
edithello.asm编辑源程序按F3再E保存退出
其它键的功能按F1帮助
masmhello.asm;把hello.asm编译成hello.obj
linkhello.obj;把hello.obj连接成hello.exe
以上两条命令中的文件扩展名可省略
打exit命令可以从DOS返回到Windows
edit可以对行号进行定位:
F6G行号
要编写32位汇编,可以到主页下载masm32
双击qeditor.exe运行32位编译环境
Project->BuildAll或Assemble&Link
Project->Runprogram运行程序
1.2.2汇编语言的应用
操作系统DOS、设备驱动程序、查错程序(debug、SoftICE)、
混合语言编程、嵌入式系统
病毒与反病毒
加密与解密
数据恢复
逆向工程:
OllyICE 主页可以下载 调试32位Windows程序
跟踪修改password.exe的过程:
F8跟踪一步
按F2设一个断点(breakpoint)
F7跟踪进入call调用内部
call之前通常用push来传递函数的参数
Ctrl+G输入地址可以在代码窗/数据窗中定位到该地址
strcmp(a,b)若a==b,则函数值=0,否则函数值≠0
无条件跳转指令jmp(jump)
可以把jnz401043改成
jmp401034
修改EXE文件的工具QuickView主页下载
开始->运行->command进DOS方式
假定QV安装在D:
\QV,password.exe也拷贝在
此文件夹内,输入以下命令进入QV文件夹
D:
CD\QV
QVpassword.exe 用工具打开该EXE文件
先按2次回车切换到汇编指令方式下,再按F2切换到
32位汇编模式。
按F7搜索特征机器码750F6854
光标定位到1032地址,再按Tab键跳到汇编代码处,
输入jmp1034。
按Alt+F9保存。
按Esc退出。
1.3怎样学好汇编语言
"Theonlywaytolearnanewprogramminglanguageisbywritingprogramsinit."---BrianW.Kernighan&DennisM.Ritchie
"Thebestwaytobecomeabetterprogrammeristowriteprograms."---JamesSinnamon
1.4第一个汇编语言程序
datasegment
hidb"Hello,world!
",0Dh,0Ah,"$"
dataends
codesegment
assumecs:
code,ds:
data
main:
movax,data
movds,ax
movah,9
movdx,offsethi
int21h
movah,4Ch
int21h
codeends
endmain
第2章 数据的表示方式和运算
2.1 数制
2.1.1 二进制数(TheBinaryNumberingSystem)
每个位共有0-1两个数字的变化,运算时“逢二进一”,“借一当二”。
二进制数在汇编语言中表示:
加后缀B或b,例如:
10110110B 10110000b
movax,1010B 相当于
movax,0Ah 相当于
movax,10
2.1.2 十六进制数(TheHexadecimalNumberingSystem)
十六进制数在汇编语言中表示:
加后缀H或者h,例如:
2564h 1B7Ch 4Ch
如果16进制数以字母开头,则前面还需要加0,例如:
0BC7Dh 0Dh 0Ah
2.2 二进制数据的组织
基本概念:
bit,byte,word,doubleword
① bit:
位
② byte:
字节
1字节=8位
字节是计算机存储和处理信息的基本单位。
byte相当于C语言中的
unsignedchar范围[0,255]即[00h,0FFh]
③ word:
字=2字节=16位 相当于C语言中的
unsignedshortint范围[0,65535]
即[0000h,0FFFFh]
③ doubleword=2字=4字节=32位:
双字
相当于C语言中的unsignedlongint
2.3 符号数(SignedNumbers)的表示
① 正数的表示:
最高位=0
8位正数
最小值
最大值
进制
00000000
01111111
二进制
00h
7Fh
十六进制
0
+127
十进制
16位正数
最小值
最大值
进制
00000000000000000
0111111*********
二进制
0000h
7FFFh
十六进制
0
+32767
十进制
32位正数
最小值
最大值
进制
00000000
7FFFFFFFh
十六进制
0
2147483647
十进制
② 负数的表示:
二进制补码(two’scomplement)
8位负数:
-128~-1
最小值
最大值
进制
10000000
11111111
二进制
80h
0FFh
十六进制
-128
-1
十进制
16位负数
最小值
最大值
进制
10000000000000000
1111111*********
二进制
8000h
0FFFFh
十六进制
-32768
-1
十进制
32位负数
最小值
最大值
进制
80000000h
0FFFFFFFFh
十六进制
-2147483648
-1
十进制
③ 符号数的表示
8位符号数(在C语言中对应的数据类型为char)
最小值
最大值
进制
10000000
01111111
二进制
80h
7Fh
十六进制
-128
+127
十进制
16位符号数(在C语言中对应的数据类型为shortint)
最小值
最大值
进制
10000000000000000
0111111*********
二进制
8000h
7FFFh
十六进制
-32768
+32767
十进制
32位符号数(在C语言中对应的数据类型为longint)
最小值
最大值
进制
80000000h
7FFFFFFFh
十六进制
-2147483648
+2147483647
十进制
0扩充及符号扩充问题:
非符号数扩充时,前面补0;
unsignedchara=255; 8位非符号数
shortintb;16位符号数
b=a; b=0000000011111111=255
被扩充的数必须是非符号数,才可以使用零扩充,
与扩充以后的数的类型无关。
被扩充的数必须是符号数,才可以使用符号扩充,
与扩充以后的数的类型无关。
符号数扩充时,前面补原数的最高位。
chara=-1; 8位符号数11111111
shortintb;16位符号数
b=a; b=11111111 11111111=-1
a=127; 01111111
b=a; 0000000001111111=127
其中偏置指数并非真正指数,
真正指数=偏置指数-127=133-127=6
尾数前面有一个隐含的起始位1及小数点,
实际尾数=1.11111101100000000000000
所以,根据指数值6把小数点右移6位得到:
1111111.01100000000000000=127.375
2.5 符号扩展(SignExtention)与零扩展(ZeroExtention)
当把8位非符号数转化成16位数时需要进行零扩充;
当把16位非符号数转化成32位数时也需要进行零
扩充。
零扩充的规则是:
扩充的各位一律为0。
符号扩充的规则是:
把被转化数的最高位填充到扩充的各个位中。
2.6 字符的表示
(1)在汇编语言中,字符与它的ASCII码是等价的。
字符在本质上是一个8位数。
例如:
'A'与65等价。
(2)数字0-9与字符’0’-’9’的相互转化:
数字+'0'=字符 3+'0'→ '3'
字符-'0'=数字 '8'–'0'→8
(3)大小写字母的相互转化
大写字母+20h=小写字母
小写字母-20h=大写字母
moval,'A'
addal,20h;AL='a'
2.7 二进制数据的运算
2.7.1 算术运算
加、减、乘、除、求余
2.7.2 逻辑运算
与、或、异或、非
1and1=1 1or1=1 1xor1=0
0and1=0 0or1=1 0xor1=1
1and0=0 1or0=1 1xor0=1
0and0=0 0or0=0 0xor0=0
①与运算可以使某些位变0;
设a是一个8位数,要使该数的最低位与最高位都变0,
其它位不变:
?
011011?
01111110 and)
00110110
②或运算可以使某些位变1;
?
011011?
10000001 or)
10110111
③异或运算可以使某些位反转;
10110110
10000001 xor)
00110111
④异或运算还有以下规律:
假定XxorY=Z,则有:
XxorZ=Y,并且YxorZ=X。
2.7.3 移位运算
左移:
<< shl:
shiftleft
右移:
>> shr:
shiftright
左移、右移、循环左移、循环右移等。
第3章8086/8088微型计算机系统组成
3.1 微型计算机系统概述
3.1.1 微型计算机硬件组成
3.1.2 微型计算机软件组成
3.2 8086/8088CPU功能结构
3.2.1 8086/8088CPU编程结构
8086共有14个寄存器(register),每个寄存器都是
16位:
AX,BX,CX,DX,SP,BP,SI,DI,
CS,DS,ES,SS, IP, FL
段寄存器(用来存放段地址) 指令指针 标志寄存器
IP:
InstructionPointer
FL:
flag
IP=将要执行的那条指令的偏移地址
80386以上的CPU有超过14个寄存器,除了段寄存器是
16位,其余寄存器都是32位:
e:
extended
EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
CS,DS,ES,SS,FS,GS,EIP,EFL
(段寄存器,是16位)
3.2.2 8086/8088的内部寄存器
1.通用寄存器
(1)数据寄存器AX、BX、CX、DX。
AH是AX的高8位,AL是低8位
数据寄存器主要用于算术、逻辑运算。
(2)变址寄存器SI、DI。
(3)地址指针寄存器SP、BP。
8086中SP有专门用途,不能放在[]中表示地址,
于是增加BX表示地址。
因此,8086中只有
BX、BP、SI、DI可以放在[]中表示地址。
80386中取消了限制,除了S结尾的段寄存器、
EIP、EFL外都可以放到[]中表示地址。
地址 值
+1000:
1000 34h;1234h的偏移地址是1000h
+1000:
1001 12h
+1000:
1002 56h
+1000:
1003 78h
movax,1000h
movds,ax;DS=1000h
movsi,1000h
moval,byteptrds:
[si];AL=34h
moval,byteptrds:
[1000h];AL=34h
movax,wordptrds:
[1000h];AX=1234h
ptr:
pointer指针
在程序中,段地址必须用段寄存器表示,不能用常数
movax,wordptr1000h:
[1000h]错误
变址寄存器与指针寄存器主要用来表示偏移地址,但也可以用于算术、逻辑运算。
2.段寄存器CS、SS、DS、ES
CS:
codesegment
DS:
datasegment
SS:
stacksegment堆栈段
ES:
extrasegment附加段
段地址:
[偏移地址]用来表示该地址对应内存单元中的值
例如:
设DS=1000h,BX=1234h
movah,ds:
[1234h];直接寻址
movah,ds:
[bx] ;间接寻址
3.控制寄存器IP、FL
IP:
instructionpointer指令指针
该寄存器与CS配合起来指向将要执行的那条指令。
其中CS表示段地址,IP表示偏移地址。
CS:
IP→下一条指令
不能通过mov指令来改变CS及IP的值。
FL称为标志寄存器(Flags),它是16位的寄存器,
但只用其中9位,这9位包括6个状态
标志和3个控制标志,如下所示:
ODITSZAPC
CF:
进位标志(carryflag)
moval,0FFh 11111111
addal,2 100000010+)
此时,CF=1 1
00000001
00000011-)
00000100 此时CF=0
clc;强制使CF=0 CLearCarryflag
stc;使CF=1 SeTCarryflag
OF(OverflowFlag)溢出标志:
两个正数相加结果是负数,
两个负数相加结果是正数就溢出,一正一负相加不会溢出
moval,7Fh;7Fh=+127
addal,1 ;AL=80h=-128此时OF=1,CF=0
moval, 80h
addal,0FFh;AL=7Fh,OF=1,CF=1
10000000=-128 80h+0FFh
11111111=-1 +)
01111111=+127 此时,OF=1,CF=1
CF=1表示非符号数溢出;
movah,0FFh;AH=255
addah,1 ;AH=0,CF=1,OF=0
OF=1表示符号数溢出。
符号数运算结果错误时,就是溢出。
movah,0FFh ;非符号数0FFh=255
addah,1 ;AH=0,CF=1
非符号数溢出使CF=1
符号数溢出使OF=1
SF(SignFlag)符号标志:
记录运算结果的符号,
结果为负时置1;否则置0。
SF=运行结果的最高位(符号数)
moval,1
addal,2;AL=3=00000011,此时SF=0
moval,0FFh
subal,1 ;AL=0FEh=11111110,SF=1
ZF(ZeroFlag)零标志:
运算结果为零时,ZF=1;否则,ZF=0。
subax,ax;AX=0,ZF=1
addax,1 ;AX=1,ZF=0
CF OF ZF SF 与这些标志位相关的有对应的
跳转指令:
jc jnc jo jno jz jnz js jns
movax,1
subax,2;CF=1,SF=1,ZF=0,OF=0
jo overflow;jumpifoverflow不成立
jc less ;jc:
jumpifCF==1 条件成立
js negative;js:
jumpifSF==1条件成立
jz zero ;jz:
jumpifzero条件不成立
jnznotzero;jnz:
jumpifnotzero成立
mov指令不会改变任何标志位
movax,2
subax,1;AX=1,ZF=0(表示结果非零)
movax,0;AX=0不影响ZF,所以ZF=0
jz zero;条件不成立
AF(AuxiliaryCarryFlag)辅助进位标志:
记录运算时第3位(半个字节)产生的进位值或借位值。
第3位有进位或借位时,AF=1;否则,AF=0。
低4位向高4位产生进位或借位
moval,23h
addal,1Fh;AL=42h,AF=1
0010 0011
000111111+)
0010
PF(ParityFlag)奇偶标志:
当结果操作数(一个字节数据或字数据)的
低8位中“1”的个数为偶数时,PF=1,否则,PF=0。
moval,2
addal,1;AL=3=00000011,PF=1
DF(DirectionFlag)方向标志:
控制字符串的操作方向。
当DF=0时为正方向(低地址到高地址),当DF=1是反方向。
cld指令使DF=0,std指令使DF=1
若源数据首地址>目标数据首地址,则复制时要按正方向
(从低地址到高地址);
若源数据首地址<目标数据首地址,则复制时要按反方向
(从高地址到低地址);
标志位DF控制字符串操作的方向。
当DF=0时为正方向,DF=1时为反方向。
用指令cld使DF=0,用指令std使DF=1。
cld:
cleardirection
std:
setdirection
IF(InterruptFlag)中断标志:
当IF=1时,允许中断;否则,关闭中断。
cli指令使IF=0表示关/禁止中断;
sti指令使IF=1表示开/允许中断。
TF(Trace/Trap Fla