汇编的学习

**机器语言

是机器指令的集合 早期的程序员用0 1数字编成程序代码

汇编语言的组成

1.汇编指令:机器码的助记符,有对应的机器码
2.伪指令:没有对应的机器码,由编译器执行,计算机并不执行
3.其他符号:如+、-、*、/等,由编译器识别,没有对应的机器码。

汇编语言的核心是汇编指令,决定汇编的特性。

先来看寄存器。CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。

但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的。有人比喻寄存器是 CPU 的零级缓存。

寄存器种类

早期的 x86 CPU 只有8个寄存器,而且每个都有不同的用途。现在的寄存器已经有100多个了,都变成通用寄存器,不特别指定用途了,但是早期寄存器的名字都被保存了下来。

EAX:针对操作数和结果数据的累加器

EBX:DS段中的数据指针 基址寄存器

ECX:字符串和循环操作的计数器

EDX:I/O指针 数据寄存器

主要用在算术运算(add、sub、xor、or等)指令中,常常用来保存常量于变量的值。某些汇编指令(mul、div、lods等)直接用来操作特定寄存器,执行这些命令后,仅改变特定寄存器中的值。

EDI(字符串操作目标指针)栈指针寄存器

ESI:(字符串操作源指针)源变址寄存器

EBP:(ss段中栈内数据指针)扩展基址指针寄存器

ESP:(ss段中栈指针)栈指针寄存器;某些指令(push、pop、call、ret)可以用来直接操作esp;站区域管理是程序中重要的一部分。

主要用作保存内存地址的指针

上面这8个寄存器之中,前面七个都是通用的。ESP 寄存器有特定用途,保存当前 Stack 的地址。我们常常看到 32位 CPU、64位 CPU 这样的名称,其实指的就是寄存器的大小。32 位 CPU 的寄存器大小就是4个字节。

储存单元

存储器被划分成若干个存储单元,每个存储单元从0开始顺序编号。

cpu对存储器的读写
存储单元的地址(地址信息)
器件的选择,读或者写的信息(控制信息)
读或者写的数据(数据信息)

cpu从3号单元中读取数据的过程
在这里插入图片描述

1.cpu通过地址线将地址信息3发送出去
2.cpu通过控制线发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据。
3.存储器将3号单元中的数据8通过数据线送入cpu

略过部分感觉无必要以后加入

第二章 寄存器

cpu的工作原理
一个cpu由运算器、控制器、寄存器等器件组成,器件靠内部总线相连。
x8086cpu的14个寄存器:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DC、ES、PSW
8086cpu所有的寄存器都是16位,可以存放两个字节。

16位数据在寄存器中的存放情况

数据:16
二进制:10010
在寄存器ax中的存储:按照顺序放入0-15

数据:20000
二进制表示:0100111000100000

一个16位寄存器所能存储的最大数据位2的16次方-1

ax分为ah和al,高低位之分,可以独立使用

为了保证兼容性,四个寄存器都可以分为两个独立的8位寄存器使用;
ax可以分为ah和al
bx可以分为bh和bl
cx可以分为ch和cl
dx可以分为dh和dl

首先cpu只是负责运算的,不用来存储数据。数据一般存储在内存之中,cpu在使用时就去内存读写数据,但是cpu的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。
但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。
寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的

内存模型:heap
寄存器只能存储少量的数据,大多数时候,cpu要指挥寄存器,直接跟内存交换数据。

程序运行的时候,操作系统会给它分配一段内存,用来存储程序和运行产生的数据。这段内存有起始地址和结束地址,比如从0x1000到0x8000,起始地址就是较小的那个,较大的为结束地址。

由用户主导请求而划分出来的内存区域叫做堆(heap)。他由起始地址开始,从低位到高位增长。heap的一个重要特点就是不会自动消失。必须手动释放,或者由垃圾回收机制来回收。

Stack:除了heap以外其他的内存占用叫做栈(stack).。就是stack由于函数运行产生的临时占用内存区域。

例如

int main(){
	int a=2;
	int b=3;
}

系统开始执行main函数时,会为它在内存里面建立一个帧(frame),所有main的内部变量(比如a和b)都保存在这个帧里面。main函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。

栈内存在进程中的作用如下:
1.暂时保存函数的局部变量。
2.调用函数时传递参数。
3.保存函数返回后的地址。

栈帧:利用ebp寄存器访问栈内局部变量、参数、函数返回地址等的手段。esp寄存器承担着栈顶指针的作用,而ebp寄存器则负责行使栈帧指针的职能。

段寄存器

段寄存器:段时一种内存保护技术,他把内存划分为多个区段,并为每个区域富裕起始地址、范围、访问权限等,以保护内存。此外,他还同分页技术一起用于虚拟内存变更为实际物理内存。段内存记录在sdt(段描述符表)中,而段寄存器就持有这些sdt的索引。

CS:代码段寄存器
SS:栈段寄存器
DS:数据段寄存器
ES:附加(数据)段寄存器
FS:数据段寄存器
GS:数据段寄存器

程序状态与控制寄存器
EFLAGS:标志寄存器

字节序:是多字节数据在计算机内存中存放的字节顺序。
主要分为小端序,大端序。
数据类型位字节型byte时,长度为1字节,保存这样的数据时,都是一样的,但是在数据长度为2个字节以上时,采用不同字节序保存的顺序是不同的。大端序:内存地址低位存储数据的高位。小端序:高对高。

大端序:常用于unix服务器的risc系列的cpu中。网络协议中也经常采用大端序方式。

PE文件格式

在这里插入图片描述
OBJ文件之外的所有文件都是可执行的。DLL、SYS文件虽然不能直接在Shell中运行,但是可以使用其他的方法执行。
并且OBJ文件也视为PE文件。但是OBJ文件本身不能以任何形式执行。
在这里插入图片描述

VA:指的是进程虚拟内存的绝对地址
RVA指从某个基准位置(ImageBase)开始的相对地址。
VA=RVA+ImageBase

PE头:由许多结构体组成。
包括
DOS头:所有的PE文件在开始部分都有DOS签名(“MZ”)
DOS存根:在DOS头下方,是个可选项,且大小不定。即使没有DOS存根,文件也能正常运行。DOS存根由代码还有数据混合成。

在这里插入图片描述

NT头:

在这里插入图片描述
NT头:文件头
有四个重要的成员:
1.Machine码:用来标识cpu
在这里插入图片描述2.NumerOfSections
用来指出文件中存在的节区数量。一定要大于0,且当定义的节区数量与实际的节区不同时,将会发生错误。
3.SizeOfOptionalHeader
指出长度
4.Chaeacteristics
标识文件的属性,文件是否可以运行,是否为DLL文件。

NT可选头:
节区头:把PE文件创建成多个节区结构的好是:可以保障程序的安全性。
**

RVA to RAW

**

PE文件从磁盘到内存映射的内容,PE文件加载到内存时,每个节区都要能准时完成内存地址与文件偏移的映射。
方法:1.查找RVA所在节区。
2.使用简单的公式计算文件偏移RW
在这里插入图片描述
在这里插入图片描述
省略我不会,看不懂。

**

IAT

**
DLL:1.不要把库包含到程序中,单独组成DLL文件,需要时调用即可。
2.内存映射技术使加载之后的DLL代码、资源在多个进程中实现共享。
3.更新库时只要替换相关DLL文件即可,简便易行。
加载DLL的方式 :
1.显式链接,程序使用DLL时加载,使用完毕后释放内存。
2.隐式链接,程序开始时即一同加载DLL,程序终止时再释放占用的内存。

机器语言的算法:
mov 寄存器 数据
mov 寄存器 寄存器
mov 寄存器 内存单元
mov 内存单元 寄存器
mov 段寄存器 寄存器

add、sub也是如此

内存单元是什么:随机存储器(RAM),只读存储器(ROM),以及高速缓存(CACHE)。只不过因为RAM是其中最重要的存储器.

一个内存单元的大小是一字节,也就是8比特,是一串8比特的二进制数。

在计算机中最小的信息单位是bit,也就是一个二进制位,8个bit组成一个Byte,也就是字节。一个存储单元可以存储一个字节,也就是8个二进制位。计算机的存储器容量是以字节为最小单位来计算的,对于一个有128个存储单元的存储器,可以说它的容量为128字节。

如果有一个1KB的存储器则它有1024个存储单元,它的编号为从0-1023。存储器被划分成了若干个存储单元,每个存储单元都是从0开始顺序编号,如一个存储器有128个存储单元,则它的编号就是从0-127

栈顶超界:
例如8086cpu用ss和sp指示栈顶的地址,通过push和pop实现入栈和出栈。
如果超出继续执行,栈下的数据将会被覆盖。
push 寄存器 将一个寄存器中的数据压入栈
pop 寄存器 出栈 用一个寄存器接受出栈的数据
可以在段寄存器和 内存单元中实现。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值