简单认识三个概念在 Windows 中,可以将 package 视为包含相关代码和配置的文件夹,crate 通常对应着主要的 rs 文件(对于库 crate 可能是 lib.rs ,对于可执行 crate 可能是 main.rs ),而模块就是通过 mod 关键字在 rs 文件中定义的有特定功能和作用域的代码块。
package包含一个 Cargo.toml 文件,阐述如何去构建这些 crate。
可以包含多个二进制create和一个库create
crate(截图crate写错了)分为两种类型
二进制项目
sec/main.rs
库 并没有 main 函数,它们也不会编译为可执行程序,它们提供一些诸如函数之类的东西,使其他项目也能使用这些东西。
src/lib.rs
mod
路径通过路径来找到自己想使用的模块或者函数
与文件系统类似,存在绝对路径与相对路径,推荐使用绝对路径编写代码,这样不担心模块移动以后触发bug
绝对路径:从crate开始编写,使用crate名字或直接写
相对路径:使用self或者super或者当前包名
标识符之间使用::分割
12345678910111 ...
编程语言
未读为什么要用枚举1234567891011121314// 定义一个名为Point的结构体struct Point { x: i32, y: i32,}//结构体主要用于将多个不同类型的数据组合成一个有机的整体,它侧重于数据的聚合。每个结构体实例都包含所有定义的字段,就像一个包含多个属性的对象。例如,Point结构体的每个实例都有x和y坐标。// 定义一个名为ConnectionStatus的枚举enum ConnectionStatus { Connected, Disconnected, Connecting,}//枚举侧重于表示一个值可以是几种不同的情况之一。它就像一个开关,可以是其中一个特定的状态。比如ConnectionStatus枚举的一个值只能是Connected、Disconnected或者Connecting中的一种情况。
定义简单枚举枚举声明某个值是一个集合中的一员
IP 标准:IPv4(version four)和 IPv6(version six)
常规ip要么是v4要么是v6,我们可以枚举 ...
编程语言
未读定义struct使用struct关键字定义名称,大括号内定义属性的名称和类型,以逗号分割每一个属性,最后一个属性也要加上逗号
使用struct需要实例化,赋值的时候顺序可以无序,但是需要写明属性名称
使用结构体属性的数值只需要加点即可
1234567891011121314struct xiu { name:String, age:i32,}fn main() { let xu = xiu{name:String::from("xu"),age:18}; println!("{}{}",xu.name,xu.age); }
如果需要修改struct的值就需要加上mut关键字,这时候整个struct属性都是可变的
12345678910111213141516struct xiu { name:String, age:i32,}fn main() { let mut xu ...
所有Rust程序都需要管理他们使用计算机内存的方式,主要用于对空闲内存的回收,在Rust编程语言在我们需要考虑代码运行在哪个上面
java的垃圾收集器会自动寻找不再使用的内存,C语言必须自己显示的分配和手动释放内存
栈内存stack压栈出栈,存储在栈内存上的数据必须拥有固定的大小,可能发生变化的值要放在heap上,操作系统放入数据只需要存放在stack的顶端即可,不需要寻找空间,函数调用过程就相当于压栈,函数执行结束时会弹出
堆内存heap堆内存存放数据会申请一块区域,当存入数据时操作系统会分配这块内存中的一部分并返回一个指针,操作系统放入数据需要记录,访问数据需要借助指针,延缓了访问速度
String12345678fn main() { let mut s = String::from("hellow");//::表示from是来自String类型的函数,该类型可以被修改 s.push_str(" World!"); println!("{}",s);}
Stri ...
编程语言
未读变量可变性let声明变量
const声明常量,常量规范全大写
隐藏shadowing
shadowing可以改变原有变量的类型,例如字符串可以被重新修改为整数型
Rust是静态编译语言,编译时必须确认所有数据类型,编译器根据变量的值通常可以自己判断一些类型
但是如果调用了一些方法进行数据类型转换就需要添加具体类型的标注
123456fn main() { let test:i32 = "200".parse().expect("error...");//parse方法是一个非常常用的方法,它用于将字符串(&str)转换为其他类型 println!("{}",test);}
标量类型整数类型整数类型的大小
123456fn main() { let test:u32 = 200;//无符号整数类型,占据32位空间,无符号以u开头,有符号以i开头 println!("{}",test); ...
猜数游戏-一次猜测let,match方法
1234567891011use std::io;//使用通用io库fn main() { println!("请猜测一个数字!");//调用宏打印提示 let mut guess = String::new();// let用来声明常量或不可变变量。let mut用来声明可变变量。 //new创建类型实例 io::stdin().read_line(&mut guess).expect("error");// println!("您猜测的数字是:{}",guess);}
生成随机数字
12345678910111213141516171819202122232425262728293031//! 猜数字游戏实现// 导入标准库的输入输出模块use std::io;// 导入随机数生成器特性(trait)以使用随机数功能use ...
编程语言
未读Rust简介用来替换C/C++,很多问题在编译阶段就可以被消除,Rust速度运行非常快
Rust可以用于编写web服务,命令行,嵌入式设备,Rust是预编译语言
安装https://www.rust-lang.org/
访问安装环境
123rustup update /更新Rustrustup self uninstall /卸载rustup doc /本地文档
开发工具建议使用vscode加rust插件
简单使用
123fn main(){ //定义main函数,无参数,无返回值 println!("hello world!");//Rust缩进为四个空格,!表示调用宏,不是调用函数}
rustc只适合运行简单Rust程序,后续会用到cargo
CargoCargo是Rust的包管理工具,可以用于现在依赖库,构建代码,安装Rust环境时自带
创建项目
cargo会自动生成git配置目录等,本地学习可以不理会其余目录,src存放了我们需要编写的源码文件
cargo.toml,cargo配置文件
在R ...
编程语言
未读定义方法方法具有很强的关联性,方法一般定义在struct、enum、trait的上下文中
impl关键字
123456789101112131415161718#[derive(Debug)]struct cfx{ length:u32, width:u32,}impl cfx { fn area(&self) -> u32{ self.length*self.width }}fn main() { let cfx1 = cfx{length:30,width:50}; println!("{}",cfx1.area());}
关联函数String::from就是关联函数
不把self作为第一个参数
关联函数通常用于构造器
12345678910111213141516171819202122232425#[derive(Debug)]struct cfx{ le ...
PE头入口和代码开始不是一个概念
一个exe运行的时候需要借助其他的资源,也就是多个PE文件组成,每个pe文件都有自己的imagebase,为了保证主程序正常运行采用了,imagebase+OEP的方式定入口点
filebuffer在内存中与在硬盘里一模一样,buffer需要运行起来需要PE loader拉伸成windows系统遵守的格式
filebuffer拉伸成imagebuffer,通过PEloader加载
1、DOS头:
WORD
e_magic
“MZ标记”用于判断是否为可执行文件.
DWORD
e_lfanew
PE头相对于文件的偏移,用于定位PE文件
2、标准PE头:
WORD
Machine;
程序运行的CPU型号:0x0任何处理器/0x14C386及后续处理
WORD
NumberOfSections
文件中存在的节的总数,如果要新增节或者合并节就要修改这个值.
DWORD
TimeDateStamp;
时间戳:文件的创建时间(和操作系统的创建时间无关)
DWORD
PointerToSymbolTabl ...
下载12滴水官网https://www.bcdaren.com/download/downdesc/356797348753707008
winhex打开未运行的记事本
打开在内存中的记事本,运行记事本程序
对比普通程序从00000000开始
内存中的程序不是
普通程序有一块空白区
内存中的程序空白区比较大
PE.exe .dll .sys 开头都是4D5A,他们属于一种叫做可执行文件的头部标识
像.txt这类文件需要借助notepad等其它程序才能被打开的文件不属于可执行文件
不同的操作系统有不同的文件规范
PE结构分节每个程序都有自己独立的4GB虚拟空间,不同的编译器有不同的PE结构对齐方式,硬盘对齐200h字节和内存对齐1000h字节
程序分节方便多开等操作,只读数据区就不需要再开辟空间
左侧在硬盘里,右侧在内存里
块表,也叫节表,记录了程序的每节在内存中哪里开始哪里结束
PE头和DOS头会对这个文件做简单的描述,比对堆栈分多大,程序运行是一个拉伸过程
查找打开notepad.exe
DOS头,在内存中以字节为单位显示一般软件都是高位在前低位在后,两个十六进制数是一个 ...