<汇编语言程序设计> 课堂笔记

1.小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

 

2.MD5加密:单向算法,只能从字符串计算出MD5值,不能逆向计算出源代码(因为并非一一对应的,可能有多个源码对应一个MD5)。MD5的碰撞。应用:RAR密码

 

3.静态的数据(RAR,图片等)加密后一般无法破解。

 

4.破解的方法:①.找出加密原理 ②.绕过判断机制(低级)

 

5.RSA加密:双密钥算法(公钥和私钥,不能互推),涉及素数,取模计算(将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥)。公钥只用来加密(一般是公开的),私钥只用来解密(关键,不公开),只有知道私钥才能解密,否则即使是加密者也无法解密。应用(广泛):数字签名,email加密。

 

6.注册码的生成方法之一:EXE内只有公钥及N,作者本人有私钥,用户的mac地址作为机器特征码,

m' =RSA(mac,公钥)发送给作者,作者先收取mac地址 = RSA(m',私钥),计算注册码 sn =RSA(mac,私钥)返回给用户,软件再对sn进行计算y = RSA(sn,公钥),if( y==mac ) Success!

破解思路:替换EXE内的公钥为自己知道的一组密钥,以此计算出一组注册码给修改过的软件校验。

 

7.机器语言不能直接删除,否则会使后面的地址全部往上填充进来,这样会影响后面的涉及地址跳转的操作。方法:①把需要修改的操作机器码都改成 90 (nop—No Operation)

 ②改成jump+ 地址,跳转到验证完的地址

 

8.修改exe文件:010Editor(只能查看16进制),QuickView(可以查看16进制和汇编代码)

QuickViewF7搜索,F2在16位汇编和32位汇编切换,F3撤销,

Tab在机器码与汇编码间切换,Alt+F9保存,F1帮助

 

9.寄存器ds只能赋值为另一个寄存器的值而不能直接赋值为常数

 

10.data代表字符串abc的段地址,而offset abc是abc的偏移地址,段地址:偏移地址 ->组成一个完整的地址

 

11.Build == compile +link

    assemble == compile : asm-->obj

    link : obj-->exe

 

12.表示一个十六进制常数时,必须用数字开头(如果是字母就添0)

 

13.C语言数字类型的对应关系:

unsignedchar = byte(8位)                        db(definebyte)

unsignedshort int = word(16位)                dw

unsignedlong int = double word(32位)        dd

 

 

14.定义一个char的变量a:

a db 12h    ; unsigned char a = 0x12

 

 

15.小端模式(Little Endian):与书写习惯相反,比如存放一个变量long long a = 0x12345678h

变量的地址为1000,则连续地址存放的数据: 1000:78h 1001:56h  1002:34h  1003:12h

意义:a仍为long long,定义char b,若执行b =a,则a会自动强制转换为8位的char,小端模式使其只取首地址抛弃之后多余的地址的值

即只将地址1000里的78h赋值给b,亦即把最低位开始的值赋值给b,符合常规的思维习惯

 

16.char->unsignedint ,假定unsigned int 是16位(如TC环境)

若原先的8是符号数,则需要进行符号扩充,规则:左边补上的位值 = 原数的最高位(即正数补0,负数补1)(正数不变)

1111 1111 -> 11111111 1111 1111

char 的-1 -> unsigned int 的 -1

符号扩充只跟被扩充数的类型有关(即只要它是符号数就必须进行符号扩充),与扩充以后的目标类型无关(即不管它是有符号还是非符号)

 

17.unsiged char ->int / unsigned int

规则:左侧一律补0

 

18.小数在内存中的保存:如 float x = 127.375(四个字节)

01000010 1111111011000000 00000000

   0               1000010 1           1111110 1100000000000000

符号               偏置指数(8位)        尾数(23位)

偏置指数 = 133

则实际指数 = 133-127 = 6

对尾数的处理:先在前面添加一个1凑够24位,并且在这个1后添加一个小数点 1.1111110 11000000 00000000

将小数点向后移动6位,变成 1111111.0 11000000 00000000

可得实际数据                        127.375 (小数点后第n位的权值为2^-n)

 

 

19.console application可以单步往下跟

    windows application里面有消息循环,所以通常用单步跟踪无法到达注册码判断的位置

所以必须要有切入点,即找出注册码判断时可能调用的判断函数

一般是MessageBoxA(弹出消息框),CreateWindow(),ShowWindow(),【DestroyWindow()】(一般离判断最近)

 

20.常用拦截API:CreateFileA()与打开文件有关(之后又ReadFile()读取文件内容)

RegCreateKey(),RegOpenKey()

 

21.filemon可以监视打开并写入到什么文件;regmon可以监视注册表的写入; autoruns 可以观察开机运行程序

 

22.8086(16位)共有14个寄存器,每个寄存器都是16位(决定地址位数和int位数(宽度)):

AX,BX,CX,DX,(通用寄存器,算数运算,位运算)

SP,BP,SI,DP(用来存放偏移地址)

CS,DS,ES,SS(用来存放段地址),IP(instruction pointer,当前指令的偏移地址),FL(flag,标志寄存器)

 

23.所有类型的指针大小都等于寄存器大小,因为指针变量需要用一个寄存器来表示。

比如,在16位CPU中,si,di,bx,bp均可以表示一个指针;

32位CPU中,eax,ebx,ecx,edx,esi,edi,ebp,esp均可以表示指针

64位CPU中,rax,rbx,rcx,rdx,rsi,rdi,rbp,rsp均可以表示指针

 

24.32位CPU的地址最大值(寻址范围)为2^32-1 B,即3.多GB(即32位系统所支持的最大内存)

 

25.地址 = 段(首)地址:偏移地址(把一个物理地址用两个16位寄存器分别存储)

如一个物理地址 12398h=1234:0058=1235:0048=1236:0038=1230:0098

 

26.段首地址最后一位必须等于0

 

27.32位内存也需要分段,一是便于管理,二是段具有自己的属性,能够对某一段内存设置属性(如只读)

 

28.GDT表:

gdtr = gdt的首地址

 

29.AX由AH及AL构成,其中AH是高8位,AL是低8位。BX,CX,DX同。

mov ah,98h

mov al,0DEh

 

30.ds:[esi] 表示在ds指向的段中,取出esi所指的对象

    地址           值

31.byteptr 相当于 (char*)强制类型转换(byte一个字节,相当于char),                        2000:1000    34h

例如:                                                                        2000:1001    12h

movax,2000h                                                                2000:1002    56h

movds,ax                                                                        2000:1003    78h

movsi,1000h                                                                

mov al,byte ptr ds:[si]             ;把ds:[si]指向的数据转换为byte类型后存储到al中,AL=34h(间接寻址)        

mov ax,word ptrds:[si]                     ;AX =1234h                                        

mov eax,dword ptrds:[si]        ;eax = 78561234h

其中mov的目的地为寄存器时,byte/word/dword ptr 这三个语句可以省略

因为编译器会进行类型的检查,当检测到mov左边为寄存器时,会自动把右边的数值强制转换为与寄存器的位数对应的类型(al-8位,ax-16位)

 

32.在程序中引用某个变量,段地址必须用段地址寄存器;而偏移地址可以用寄存器(间接寻址),也可以用常数(直接寻址),或两者的组合(加减法)

 

33.若两个值相加超过了寄存器的位数,则抛弃高位只取低位

 

34.一段源程序:

datasegment

abc db1,2,3     ;char[3] = {1,2,3};

xyz dw1234h, 5678h, 9999h

data ends

codesegment

assume cs:code   ds:data

mov ah,ds:abc     abc这样写,该句编译后变成 movah,ds:[0000] ;(相当于把abc加上方括号,即取其偏移地址)

mov ah,ds:[abc]   abc本来是变量的名字,用方括号括起来就变成了它的偏移地址,编译后与上一句相同

mov   bl,ds:[abc+1]  编译后变成movbl,ds:[0001]

mov   bl,ds:abc[1]     编译后变成movbl,ds:[0001]   这里abc[1]并不是数组abc的第一个元素,而是相对于abc的地      

                                                                                           +1的地址

; mov   bl,ds:abc+1    虽然编译后同上一句,但是防止混淆应避免这样的写法

 

movcs,ds:xyz          cs = 1234h

movdx,ds:[xyz]      cs = 1234h

movsi,ds:xyz[2]      si = 5678h

mov di

movah,4Ch

 

code ends

end

 

 

35.控制寄存器:IP,FL

IP: instruction pointer 指令指针,CS配合起来指向将要执行的下一条指令

CS:IP 指向下一条将要执行的指令(32位当然是ECS:EIP)

FL:Flag

状态标志:CF,ZF,SF,OF,AF,PF(后两个较少用)

控制标志:DF,IF,TF

以上9个位都存在于标志寄存器FL

寄存器FL的长度取决于CPU位数

 

36.CF:进位标志(carry flag):随时反映当前计算结果是否有进位(或借位)

这里的进位(借位) 指的是对当前 寄存器最高位的更高位进位(或借位)

比如 al是的宽度为8, 只有计算结果需要用到第九位才叫进位(或借位)

moval,0FFh     al = 1111 1111

add al,2             al = 00000001  (FF2相加产生了进位,CF的状态会立即变为1)

有时也把CF=1称为非符号数的溢出标志(ff+2!=1,相加过程中有一位溢出)

相关指令(用途):

moval,oFFh

add al,2

jc has_carry(段名)      (jump if has carry,有进位则跳)

...

has_carry:

....      

:CF也可表示借位标志,当做减法运算产生借位时,也会变成1

 

37.OF(Overflow Flag)溢出标志(以下情形均为符号数)

溢出有两种情况:两个正数相加的结果是负数,两个负数相加的结果是正数就溢出(一正一负相加不会溢出)

moval,oFFh

add al,2

执行完后 OF=1,CF=1

相关指令jo(jump ifoverflow),jno(jump if not overflow)

 

 

38.SF(Sign Flag) = 【运算结果的最高位】

反映当前的运算结果是正的(SF=0)还是负的(SF=1)

相关的指令:js(SF=1,即有符号则跳),jns(SF=0,无符号则跳)

 

39.ZF(Zero Flag)零标志

运算结果为0,ZF=1;否则ZF=0 (应该把ZF的值理解为真和假)

subax,ax  ;AX=0,ZF=1

addax,1   ;AX=1,ZF=0

指令:jz(jump ifzero)==je

jnz(jump if not zero)==jne(机器码完全相同,两个指令等价)

原因:

cmpax,bx   

jethey_are_equal

实际上cmp指令做的是减法运算,因此ax==bx即差等于零时,ZF=1,jejz都会执行

但与减法运算sub相比,cmp指令不会改变左侧变量的值

 

40.AF(Auxiliary Carry Flag):辅助进位标志

记录运算时第五位(二进制的第n位都是右数,且最右边的为第0)产生的进位或借位值

第五位有进位或借位时,AF=1;否则AF=0

moval,23h

addal,1Fh    

 

41.PF(Parity Flag)  奇偶标志

当运算结果的低八位(即用16进制表示的2)"1"的个数为偶数时,PF=1,否则PF=0.

指令:

jp==jpe(jumpif parity even)

jnp==jpo(jumpif parity odd)

 

42.DF(DirectionFlag):

标志位DF控制字符串操作的方向,DF=0时为正方向,

DF=1时为反方向.

若源首地址<目标首地址,则复制按反方向

(如右图,左边为源地址,右边为目标地址)                        

若源首地址>目标首地址,复制按正方向

用指令cld使DF=0,用指令std使DF=1

cld(clear direction,使DF=0,表示正方向)

std(set direction,使DF=1,表示反方向)

 

 

43.IF(Interrupt Flag)中断标志:

IF=1,允许中断;否则关闭中断.

cli指令使 IF=0 表示关/禁止硬件中断

sti指令使 IF=1 表示开/允许硬件中断

 

键盘缓冲区 是一个队列(可以理解为一个数组)

charkey[100]

char *p =&key[10]

 

(时钟中断)

 

44.

TF(Trace/Trap Flag) 跟踪

你可能感兴趣的:(ASM,汇编,汇编语言,笔记)