1.进制转化
-
十进制到二进制:要将十进制数转换为二进制数,可以使用除2取余法。将十进制数反复除以2,将得到的余数从下往上排列即可得到二进制数。
-
二进制到十进制:要将二进制数转换为十进制数,可以使用权重法。将二进制数的每一位与对应的权重(权重表示每个二进制位所对应的权值。二进制数从右到左的每一位,其权值是2的幂次方,依次递增)相乘,然后将结果相加即可得到十进制数。
-
十进制到十六进制:要将十进制数转换为十六进制数,可以使用除16取余法。将十进制数反复除以16,将得到的余数从下往上排列即可得到十六进制数。对于余数大于等于10的情况,可以用字母 A-F 表示。
-
十六进制到十进制:要将十六进制数转换为十进制数,可以使用权重法。将十六进制数的每一位与对应的权重相乘,然后将结果相加即可得到十进制数。对于字母 A-F,分别表示十进制数 10-15。
2.字长与端序
1.内存以字节为单位。 一个字节是 8 个比特位,可以表示 2^8 = 256 个数。大小为 8 位的二进制数是从 0 开始到 255 这 256 个值中的一个。 两个字节被称为一个字(WORD),两个字被称为四个字节(32位)也即双字(DWORD),四字 (QWORD)是八个字节(64 位)
2.大端序(Big-Endian)将数据的低位字节存放在内存的高位地址,高位字节存放在低位地址。这种 排列方式与数据用字节表示时的书写顺序一致,符合人类的阅读习惯。
小端序(Little-Endian)将数据的低位字节放在较小的地址处,高位放在较大的地址处。小端序与 人类的阅读习惯相反,但更符合计算机读取内存的方式,因为CPU读取内存中的数据时,是从低地 址向高地址方向进行读取的。
3.汇编语言(练习)
-
该函数有一个参数,参数名为arg_0。
-
该函数使用的函数调用约定是标准的cdecl调用约定。根据该约定,参数通过栈传递,函数的返回值存储在eax寄存器中。
-
当程序执行到0x1228时,eax的值取决于函数的执行结果。根据代码逻辑,eax的值将是[ebp+var_4]的值,即最后一次mov指令将var_4的值存储到eax中。
-
int test1(int arg_0) {
int var_4 = 0;if (arg_0 < 0) {
var_4 = 1;
} else if (arg_0 == 0) {
var_4 = 2;
} else if (arg_0 <= 0x1D) {
var_4 = 3;
} else if (arg_0 <= 0x45) {
var_4 = 4;
} else {
var_4 = 5;
}return var_4;
}int main() {
int result = test1(0x3C);
return result;
}
4.IDA的安装并完成前三道题
官网下载安装免费版
借鉴博客完成
了解
1,shift+f12查找所有的字符串
2,ctrl+x(交叉引用)查看是哪段函数调用了字符串
3,f5进入伪代码
4,直接把鼠标 放到ascii编码上按“R”键就可以转换成字符
5.了解
什么是寄存器
什么是堆
什么是栈
一,汇编语言(assembly language):
我们知道,CPU 只负责计算,本身不具备智能。你输入一条指令(instruction),它就运行一次,然后停下来,等待下一条指令。这些指令都是二进制的,称为操作码(opcode)。编译器的作用,就是将高级语言写好的程序,翻译成一条条操作码。汇编语言是二进制指令的文本形式,与二进制指令是一一对应的关系!
二,寄存器("CPU 的零级缓存"):
CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。
三,堆:
这种因为用户主动请求而划分出来的内存区域,叫做 Heap(堆)。它由起始地址开始,从低位(地址)向高位(地址)增长。Heap 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。
四,栈:
除了 Heap 以外,其他的内存占用叫做 Stack(栈)。简单说,Stack 是由于函数运行而临时占用的内存区域。