AI摘要
逻辑运算
或(or |)
只要有一个为1就是1
1011000101
1001100110
__________
1011100111与(and &)
两个都为1才是1
1011000101
1001100110
__________
1001000100异或(xor ^)
1011000101
1001100110
__________
0010100011
上1下0 只有这样,电路才可以连通
非(not!)
1是0 0是1
1001100110
__________
0110011001左移(<<)
0010<<0100
计算机如何计算2 + 3
X:0010
Y:0011
xor X Y = R = 0001
如何判断3+2计算完毕
and X Y = Z = 0010
Z<<0100 根据这个结果是否为0判断计算是否结束
Y:0100
X:0001
xor X Y = R = 0101
X:0001
Y:0100
and = 0000
0000<<1 = 0000 R = 0101
逻辑运算在客户端和服务器加密的应用
客户端:2015
秘钥:54
客户端将数据发送给服务端(加密)20 15 两个字节
00100000
xor 01010100
_____________
01110100 ->74 00010101
xor 01010100
_____________
01000001 ->41The answer is 7441
服务器:7441(服务器解密过程)
秘钥:54
01110100
xor 01010100
______________
00100000->20 01000001
xor 01010100
______________
00010101->15解密数据 = 2015
寄存器与内存
寄存器是最快的(效率高 成本高) 内存比寄存器慢(效率低 成本低)
32位通用寄存器 不用记具体用途 对我们来说他只是一个容器
几个常用的计量单位
byte(字节) = 8Bit
Word(字) = 16Bit
Dword(双字) = 32Bit
通用寄存器的使用(EAX/ECX/EDX/EBX)
MOV/ADD/SUB
mov eax,12345678
add eax,1
mov ecx,2
add eax,ecx
sub eax,3
要加上0x表示十六进制数
内存
每个内存单元的宽度为8个字节
内存单元的编号称之为地址
为什么物理机被称为32位计算机
因为寻址宽度为32位 即8个十六进制数
从0X00000000~0xFFFFFFFF
1k = 1024字节
1m = 1024k
32位的寻址宽度可以存储FFFFFFFF+1的数据
系统已经有一部分的占用,所以内存一般没有理想的那么大
内存的读写
读取内存的值
寻址公式一
MOV EAX,DWORD PTR DS:[0x13FFC4]//从后边地址取值,取32位大小的数据
MOV EAX,DWORD PTR DS:[0x13FFC8]
向内存中写入数据:
MOV DWORD PTR DS:[0x13FFC4].eax
MOV DWORD PTR DS:[0x13FFC8],ebx
获取内存编号:
LEA EAX,DWORD PTR DS:[0X13FFC4]
LEA EAX,DWORD PTR DS:[ESP+8]
DS->数据段 SS->栈段 ES->附加段
lea 取地址编号
寻址公式二:[reg] reg代表寄存器可以是8个通用寄存器中的任意一个
读取内存的值:
MOV ECX.0x13FFD0
MOV EAX,DWORD PTR DS:[ECX]
向内存中写入数据:
MOV EDX.0x13FFD8
MOV DWORD PTR DS:[EDX],0x87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EDX]
MOV EAX,DWORD PTR DS:[EDX]
寻址公式三:[reg+立即数]
读取内存的值:
MOV ECX,0x13FFD0
MOV EAX,DWORD PTR DS:[ECX+4]
向内存中写入数据:
MOV EDX.0x13FFD8
MOV DWORD PTR DS:[EDX+0xC],0x87654321
获取内存编号:
LEA EAX.DWORD PTR DS:[EDX+4]
MOV EAX,DWORD PTR DS:[EDX+4]
寻址公式四:[reg+reg*{1,2.4,8}]
读取内存的值:
MOV EAX.13FFC4
MOVECX.2
MOV EDX,DWORD PTR DS:[EAX+ECX*4]//只能是1248
向内存中写入数据:
MOV EAX,13FFC4
MOV ECX.2
MOV DWORD PTR DS:[EAX+ECX*4],87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4]
寻址公式五:[reg+reg*{1,2,4,8}+立即数]
读取内存的值:
MOV EAX,13FFC4
MOV ECX.2
MOV EDX,DWORD PTR DS:[EAX+ECX*4+4]
向内存中写入数据:
MOV EAX.13FFC4
MOV ECX.2
MOV DWORD PTR DS:[EAX+ECX*4+4],87654321
获取内存编号:
LEA EAX,DWORD PTR DS:[EAX+ECX*4+2]
堆栈
1、堆栈的本质就是内存。
2、栈是用来存储临时变量,函数传递的中间结果。
3、操作系统维护的,对于“程序员"是透明的。
注:课程里面会用一周的时间来熟悉堆栈。
push esp减小 pop esp增加
作业:
push eax
等于
mov dword ptr ss:[esp-4],eax
sub esp,4
push esp
等于
mov dword ptr ss:[esp-4],esp
lea esp,dword ptr ss:[esp-4]
或者
mov dword ptr ss:[esp-4],esp
sub esp
pop esp
等于
lea esp,dword ptr ss:[esp+4]
mov esp,dword ptr ss:[esp-4]
与 push 对应的 pop 操作则相反:先降低栈顶指针,再取出数据。
或者
add esp,4
mov esp,dword ptr ss:[esp-4]
STOS(Store String)直译是 “存储字符串”,它的核心作用是:将累加器(AL/AX/EAX/RAX)中的值,存储到 ES:DI(或 ES:EDI/RDI)指向的内存地址中,并根据方向标志位(DF)自动调整 DI/EDI/RDI 寄存器的值,方便连续存储。
简单说,STOS 就是 “把寄存器里的数写到内存里”,专门用于批量填充内存(比如 memset 功能),是串操作指令中最常用的之一。
分别为Stosb stosw stosd stosq
DF=0(默认,可通过 CLD 指令设置):DI/EDI/RDI 自动递增(向高地址存储);
DF=1(可通过 STD 指令设置):DI/EDI/RDI 自动递减(向低地址存储)。
REP STOS 是 x86 汇编中高效批量填充内存的核心指令:
核心逻辑:ECX 控制次数,DI 指向目标内存,累加器提供填充值,重复执行存储操作;
典型用途:内存清零、批量赋值(如填充 NOP、初始化数据缓冲区);
关键前提:DI 必须指向当前进程的有效内存地址(否则会触发无效内存访问,和你之前 dd eax 的问题本质相同)。
作业







































