满天星
Fork me on GitHub

若水论坛汇编学习笔记01

第一节
1.为什么要学习汇编语言
有助于学习计算机底层运作,广泛应用于逆向工程,破解软件,驱动开发等
逆向:反汇编
破解:od
驱动开发:过游戏驱动保护等
2.计算机语言的分类
机器语言->汇编语言->高级语言(面向过程:C语言/面向对对象:C++)
0000001,11000011
add ax, bx
c=a+b
3.常用进制之间的转换
4.汇编语言的特点:
保持了机器语言直接面向机器的特点
有效的访问计算机硬件
代码占内存少(指编译之后的文件),执行速度快
可以与高级语言配合使用(内联汇编,_asm)
第二节
1.数据的表示
无符号数:n位无符号数的表示0=<X<=2n(次方)-1
带符号数:第一位为符号位 0 1011; 1 1011
带符号数表示方法有:原码,反码,补码,正数三者相同
非数值数据:字符,图形,汉字等ASCII码就是用来表示的非数值数据的
原码转换反码的方法:正数不变;负数符号位不变其他各位取反加1
2.计算机数据为什么要使用补码表示
1.使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理
2.两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃
(牵扯到一个溢出的问题)
3.什么是溢出
在计算机中有个缓冲区的地方,他是用来存储用户输入的数据的,缓冲区的长度是被事先设定好的,如果用户输入的数据超过了缓冲区的长度,如8位二进制数进行运算,就会溢出,如果计算机数值超出-128~+127这个范围那么就会溢出,而这些溢出的数据就会覆盖在合法的数据上,这就像杯子装水的道理,水多了杯子装不下,当然就会溢出了.缓冲区溢出漏洞主要是由于许多软件没有对缓冲区进行检查而造成
4.基本的逻辑运算
与AND 或OR 非NOT 异或XOR

第三节
1.内存容量单位
位bit 字节byte 字word
1KB
1MB=1024KB=2^20B    //8086/8088的CPU中有20根地址线,即可以访问2^20B个地址 物理地址范围:00000~FFFFF 一个F是4次方
1GB
1TB
8086/8088 16位CPU AX  寄存器前面会加个E,32位 (EAX)  段基址+偏移地址 :寻址的时候采用了此方式,进行访问主存地址 段基址只能是4位,只能存8086/8088 
2.寄存器
通用寄存器
数据寄存器: AX:加法 BX:基值 CX:计数 DX:数据
指针寄存器:SP BP SP与SS配合使用,可指向目前的堆栈位置 SP指向栈顶
变址寄存器:SI DI 存放主存操作数的全部/部分偏移量
段寄存器 CS DS ES SS
控制寄存器: IP:指令寄存器 FR:标志寄存器,存放运算结果的标志 IP存放指令偏移
3.隐含指令
MULBL  乘法指令;表示方式:  AL=AL*BL

第四节
1.堆栈特点作用--游戏辅助找call地址有用到
什么是堆栈:先进后出的内存区域. 用SS存放基址 SP存放栈顶偏移量 SS:SP构成堆栈指针  
特点 数据先进后出
作用: 中断操作/存放参数/存放子函数地址(主要应用于游戏辅助od写入断点,ctrl+d会显示堆栈的call的地址,排除之后就会找到自动打怪,自动捡物等call) 等 
reg:(假设C语言写的)
add(int a,int b)
(反汇编格式)
push eax  //叫压栈指定,需要在执行加法之前先把参数压到栈里
push ebx
call xxxx
2.PUSH/POP 执行过程分析
执行过程  PUSH src //push 一个源
          SP<-(SP)-2  //首先步骤是SP-2->SP
          SP<-src  //第二步

执行过程  POP dest
          dest<-((SP))  //从SP里面取两个字节到目标地址
          SP<-(SP)+2  //向搞地址移动两个字节(指针移动2个字节)

第五节
寻址方式-- 寻址方式就是寻找操作数或操作数地址的方式
<立即数寻址方式> (需要百度)
操作数直接存放在指令中,紧跟在操作码之后的寻址方式就是立即数寻址方式
reg:
    MOV AX,2345H  //,后面的数是立即数,即已经确定的数值
    MOV AL,OEH  
<寄存器寻址>
    操作数存放在CPU的内存寄存器的寻址方式就是寄存器寻址方式
    reg:
    MOV AX,BX   //32位是 MOV EAX,EBX
    ADD AX,BX
<存储器寻址方式>(最复杂的方式)
    8086指令系统提供了以下5种针对存储器的寻址方式
    直接寻址,寄存器间接寻址,寄存器相对寻址,基址加变址寻址和相对基址加变址寻址,用于说明操作数所在存储单元的地址
(1)直接寻址:
    指令中给出的地址码即为操作数的有效地址,就是直接寻址方式
    reg:MOV AX[2000H](有效地址,隐含的意思是在DS数据段*16+2000H的偏移所指向的内容,再传给AX)-->2000H为存放操作数单元号的符号地址
    MOV AX,2000H -> 2000H 立即数寻址,两者是不等效的
(2)寄存器间接寻址方式:
    操作数在存储器中,操作数的有效地址用 SI,DI,BX和BP四个寄存器之一来指定
    reg:MOV AX,[BX]
    计算公式:物理地址=16d*(DS)+(BX) //BX默认区段是DS段,16进制需要加两个字节(00),然后再加上BX
    物理地址=16d*(DS)+(SI)
    物理地址=16d*(DS)+(DI)
    物理地址=16d*(SS)+(BP)  //BP段 的默认区段是SS段
(3)寄存器相对寻址方式:
    reg:MOV AX,COUNT[SI]      
    MOV AX,[COUNT+SI]
    其中 COUNT为位移量的符号地址
    计算公式:物理地址=16d*(DS)+(SI)+8位位移量  //SI默认是DS段
    物理地址=16d*(DS)+(SI)+16位位移量
    物理地址=16d*(SS)+(BP)+16位位移量
    物理地址=16d*(SS)+(BP)+8位位移量
(4)基址变址寻址方式:
    reg:MOV AX,[BX][DI]
    MOV AX,[BX+DI]
    计算公式:物理地址=16d*(DS)+(BX)+(SI)
    物理地址=16d*(DS)+(BX)+(DI)
    物理地址=16d*(SS)+(BP)+(SI)
    物理地址=16d*(SS)+(BP)+(DI)
(5)    相对基址变址寻址方式:
    reg:MOV AX,MASK[BX][SI]
    MOV AX,MASK[BX+SI]
    MOV AX,[MASK+BX+SI]
    以上三个例子是等效的
    计算公式:物理地址:16d*(DS)+(BX)+(SI)+8位位移量
    物理地址:16d*(DS)+(BX)+(DI)+16位位移量
    物理地址:16d*(SS)+(BP)+(SI)+8位位移量
    物理地址:16d*(SS)+(BP)+(DI)+16位位移量
    上述共计七种操作数寻址方式,与80C51单片机的完全一致
串操作寻址方式:
I/O端口寻址方式:

第六节 
汇编指令:
Mov指令只允许一个操作数在存储器中(与LEA区分:Mov为操作的内容)
Mov eax,addr1
Mov addr2, eax    //如果想把addr1传到addr2里,不能直接mov ,需要这样两次操作

XCHG交换指令不影响任何标志位
XCHG DEST,SRC //在TP游戏保护的清0代码中用到了此指令  DEST:目的操作数 SRC:源操作数

LAHF/SAHF :取/放标志位的指令
LAHF是取,FR取标志位到AH中/SAHF是放,从AH中取标志位到FR
通常在改变标志位时使用

PUSHF:标志压栈指令,以字为单位进行压栈

LEA DEST,SRC 将存储器操作数的地址传送到指定寄存器 (与Mov区分:LEA为操作的地址)
LEA DI,TAB
LEA BX,10H[SI]

ADD/ADC 加法指令/带进位的加法指令  //ADC主要应用于32位CPU运算64位等高位加法运算
INC 自动加1指令
SUB/SBB 减法指令/带符号的减法指令
DEC 减1指令
NEG 求负数指令

CMP 比较指令,做减操作,按结果置标志位
TEST 测试指令,做与操作 // test eax,0 : 置0

AND/OR/NOT/XOR

SAL/SAR 算数左移/右移指令 右移时符号位不变
SHL/SHR 逻辑左移/右移指令 (全部都移动) 移动的位放置在CF中,影响FR标志位
ROL/ROR 循环左移/循环右移 (reg:右移时最末尾会移动到首位)
RCL/RCR 带进位的循环左移/循环右移 CF参与循环

CLC/STC/CMC : CF 置 0 / 1 ; 变反
CLD/STD : DF 置 0 / 1
CLI/STI : IF 置 0 / 1

第七节
debug的使用:
DEBUG是一个DOS实用程序,是供程序员使用的程序调试工具,可以用它检查内存中任何地方的字节以及修改任何地方的字节.它可以用于逐个指令执行某个程序以验证程序运行的正确性,也可以追踪执行过程,比较一个指令执行前后的值以及比较与移动内存中数据的范围,读写文件与磁盘扇区
DEBUG:进入debug环境
R:查看寄存器的内容 R EAX
D xxxx: xxxx 查看段基址+偏移=逻辑地址的内容
    reg:-d 0af3:0000  :显示从0af3到0000的内容;16进制;...表示ASCII没有对应的关系 
Q:退出命令
在debug中写一段程序并执行
xxxx: xxxx mov bx, ax
xxxx: xxxx neg bx
xxxx: xxxx add ax, bx
T 单步执行命令
A 反汇编命令/汇编写入之前
G xxxx
g 就是连续执行内存代码,可以在g后面指定内存地址,如g=0000:0100;也可以为g=0000:0100 0000:0200表示代码从100的内存地址执行到200的内存地址然后断住

    reg:
    -r ax
    :0007  //将ax改成0007
    -0af3:0000 mov bx,ax    //写入
    -^ Error
    -a  //输入a命令才能写入
    0AF3:0100 mov bx,ax     //0100 代表IP指针位置(即代码)  2个字节
    0AF3:0102 neg bx  //取反   2个字节
    0AF3:0104 add ax,bx  //相加后赋值给a  2个字节
    0AF3:0106   //直接回车代表编写完毕
    g 0af3:0100 0af3:0106  //这里是看执行的字节数,仅限于调试程序不能单独运行

第八节
伪指令:
VAR1 DB 00H ; DB伪指令表示给变量VAR1分配一个存储单元,初值为00H  (不占内存的指令,仅是辅助标识的作用)
MOV SI,OFFSET VAR1 OFFSET运算符伪指令将VAR1的段内偏移地址给SI
ORG 20H ORG伪指令表示起始位置从偏移量为20的地址开始有效(代码段开始位置)
PTR 属性运算符为已经分配的存储器地址赋予另外的属性
VAR1 DW?
VAR2 EQU BYTE PTR VAR1;EQU等效/BYTE属性改变为字节  (VAR1本身是DW,这里将其转为了BYTE类型)
FRR/NEAR 段内段外跳转 (段间/段内)
SEGMENT [PATA] [PUBLIC] 'DATA' *****ENDS 段定义为伪指令
ASSUME段寻址的伪指令 指定寄存器与段的对应关系如:ASSUME CS:CODE
PROC/ENDP 过程定义 (过程开头/过程结束)

第九节
编写完整的汇编程序:
(实现在屏幕中打印helloworld)
;堆栈段:    (;分号表示注释)
stack    segment    stack
        db        100(?)   //分配字节
stack    ends
;数据段
data    segment
szhello    db        'hello world',0dh,0ah,'S'
data    ends
;代码段:
code    segment
        assume  cs:code,ds:data,ss:stack
start:
        mov        ax,data
        mov        ds,ax

        mov        ah,9    ;要打印9个字符串  
        mov        dx,offset,szhello   ;将字符串的首地址放到dx中
        int        21h        ;调用21h进行显示

        mov        ah,4ch    ;返回DOS  (这里是调用了模板)
        int        21h
code    ends
        end        start

调试:
EDIT后缀为.asm--MASM/TASM9(工具)生成.obj---LINK生成.exe---DEBUG调试程序

命令:
dir 显示文件
edit 编辑修改源程序
masm 汇编源程序
link 链接目标文件
debug 调试exe文件
0dh 表示回车符合,这只是一个表示这一行终止的符号,不可见的
0ah 表示换行,就是跳转到下一行,两者用表示回车换行

cmd->masm helloworld.asm    (helloworld.asm)//进行编译,会生成.obj的文件
回车回车回车 
link helloworld.obj;   //不加;会生成很多附属文件,仅生成exe就加;
edit helloworld.asm
debug asm.exe
a   //反汇编一下
r
db 0b57

第十节
认识汇编集成开发环境Rad ASM
1.RADASM界面介绍
2.新建一个工程
3.运行上一节课代码

先编译(向下箭头) 再构建(向上箭头) !叹号是运行按钮
new -> project -> masm -> 工程类型:win32 app带窗口带资源的程序;console app不带资源;LJB库文件;Driver(.sys)汇编或C写
 //演示为Dos App -> 工程名称:test1  ; 工程说明:hello world -> 模板选择 DosExe.tpl -> 选择生成文件 -> finish

win32演示(可视化界面): DialgApp.tpl模板,如果不选模板,右键工程文件,新建,对话框,名称
-------------本文结束期待您的评论-------------