1. PUSH 指令
功能: 将操作数压入栈顶。
本质: 它是一个“先减后存”的操作。
受影响的标志位: 无。
工作原理(在 32 位模式下):
-
首先,栈指针寄存器
ESP的值会 减去操作数的字节数(例如,在 32 位模式下是 4 字节)。 -
然后,将操作数的值 存储到
ESP寄存器所指向的新内存地址。
语法:
asm
push source
操作数类型:
-
push reg: 将寄存器的值压入栈。 -
push mem: 将内存地址处的值压入栈。 -
push immediate: 将立即数压入栈。
示例:
asm
mov eax, 11223344h ; EAX = 0x11223344
push eax ; 1. ESP = ESP - 4
; 2. 将 0x11223344 存入地址 [ESP]
执行后,栈顶([ESP])的内容就是 0x11223344,并且 ESP 指向这个值。
2. POP 指令
功能: 将栈顶的值弹出到指定的操作数。
本质: 它是一个“先取后加”的操作。
受影响的标志位: 无。
工作原理(在 32 位模式下):
-
首先,从
ESP寄存器所指向的内存地址 读取值。 -
然后,将该值 存入 目标操作数。
-
最后,栈指针寄存器
ESP的值会 加上操作数的字节数(例如,在 32 位模式下是 4 字节)。
语法:
asm
pop destination
操作数类型:
-
pop reg: 将栈顶值弹出到寄存器。 -
pop mem: 将栈顶值弹出到内存地址。
示例:
asm
pop ebx ; 1. 从 [ESP] 读取值到 EBX
; 2. ESP = ESP + 4
假设执行前 [ESP] 是 0x11223344,执行后 EBX = 0x11223344,并且 ESP 指向栈中下一个位置。
PUSH 和 POP 的典型用途:
-
保存和恢复寄存器: 在函数开头保存寄存器原有值,在函数结束前恢复它们。
asm
MyFunction: push ebp ; 保存旧的栈帧基址 mov ebp, esp ; 建立新栈帧 push ebx ; 保存 EBX,因为后面我们会修改它 push esi ; 保存 ESI ; ... 函数主体,使用 EBX 和 ESI ... pop esi ; 恢复 ESI (注意:顺序与 PUSH 相反!) pop ebx ; 恢复 EBX pop ebp ; 恢复旧的 EBP ret -
传递函数参数: 在 C 语言的
cdecl调用约定中,参数从右向左依次压栈。
3. ADD 指令
功能: 将两个操作数相加,结果存回目标操作数。
公式: destination = destination + source
受影响的标志位: OF(溢出标志), SF(符号标志), ZF(零标志), CF(进位标志), AF, PF。
语法:
asm
add destination, source
操作数组合:
-
add reg, reg:eax = eax + ebx -
add reg, mem:eax = eax + [myVariable] -
add mem, reg:[myVariable] = [myVariable] + ebx -
add reg, immediate:eax = eax + 10 -
add mem, immediate:[myVariable] = [myVariable] + 10
示例:
asm
mov eax, 5 ; EAX = 5 mov ebx, 3 ; EBX = 3 add eax, ebx ; EAX = 5 + 3 = 8 add eax, 10 ; EAX = 8 + 10 = 18 ; 标志位变化示例 mov al, 0xFF ; AL = 255 (0xFF) add al, 1 ; AL = 0, 同时会设置 ZF=1 (结果为0), CF=1 (最高位有进位)
4. SUB 指令
功能: 从目标操作数中减去源操作数,结果存回目标操作数。
公式: destination = destination - source
受影响的标志位: OF(溢出标志), SF(符号标志), ZF(零标志), CF(进位标志/借位标志), AF, PF。
语法:
asm
sub destination, source
操作数组合: 与 ADD 指令完全相同。
示例:
asm
mov eax, 10 ; EAX = 10 mov ebx, 4 ; EBX = 4 sub eax, ebx ; EAX = 10 - 4 = 6 sub eax, 2 ; EAX = 6 - 2 = 4 ; 标志位变化示例 mov al, 0 ; AL = 0 sub al, 1 ; AL = 255 (0xFF), 同时会设置 SF=1 (结果为负), CF=1 (需要借位)
5. LEA 指令
功能: 将源操作数的 有效地址 加载到目标操作数。
关键点: 它不访问该地址处的内存,只计算地址本身。
受影响的标志位: 无。
语法:
asm
lea destination, source
-
destination: 必须是一个通用寄存器。 -
source: 必须是一个内存操作数。
LEA 的核心用途:
-
计算地址(本职工作):
asm
mov esi, offset myArray ; ESI 指向 myArray 的地址 lea edi, [esi + eax*4] ; 计算 myArray[eax] 的地址(假设是 int 数组),并存到 EDI。 ; 这里 EDI 得到的是地址,而不是该地址处的值。 ; 对比 MOV: mov edi, [esi + eax*4] ; 这是将 myArray[eax] 的值加载到 EDI。 -
进行复杂的算术运算(巧妙用法):
由于LEA可以执行[base + index*scale + displacement]这种形式的计算,它常被编译器用来快速执行整数乘法与加法,而无需使用MUL或ADD指令。asm
; 计算 EAX * 5 + 10 lea ecx, [eax*4 + eax] ; ECX = EAX*4 + EAX = EAX*5 lea ecx, [ecx + 10] ; ECX = ECX + 10 ; 上面两条指令可以合并为一条: lea ecx, [eax*4 + eax + 10] ; ECX = EAX*5 + 10
这比使用
imul和add指令更高效。
6755

被折叠的 条评论
为什么被折叠?



