一些指令笔记

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%
总线锁定指令 LOCK
格式:LOCK instruction (指令)
说明:为确保不可分割的读/修改/写操作的发生,在某些特殊指令的执行期间置起LOCK#信号。
当总线上有多个处理器时,这个信号对保证总线以及所有附加在总线上的内存来说是很重要的,
尤其是在一些敏感的操作期间。比如说,当一个“信号灯”正在被修改的时刻。LOCK只能用于
下列指令:
ADC,ADD,AND,BT  mem,reg/imm
BTS,BTR,BTC,OR  mem,reg/imm
SBB,SUB,XOR     mem,reg/imm
XCHG         reg,mem
XCHG            mem,reg
EDC,INC,NEG,NOT mem
CMPXCHG,CMPXCH8B
XADD
(目的操作数为内存操作数),源操作数为内存操作数,或LOCK其他指令,可能产生操作码异常#UD。
对于XCHG指令(有内存操作数时),无论是否有LOCK锁前缀,LOCK信号总是存在。
例子:
;当执行BTS时,LOCK #信号被置起。
LOCK BTS dword ptr [ESI],ECX

经典应用:
自旋锁Spin Lock(一种轻量级的多处理器间的同步机制,自旋锁对于单处理器是没有实际意义的。它要求持有锁的处理器所占用的时间尽可能短,因为此时别的处理器正在高速运转并等待锁的释放,所以不能长时间占有)

多处理机上的内核ntkrnlpa.exe自旋锁片段:
;=============================================================
;//获得锁或等待
.text:004689C0 KiAcquireSpinLock proc near            ; CODE XREF: sub_416FEE+2D p
.text:004689C0                                        ; sub_4206C0+5 j ...
.text:004689C0                lock bts dword ptr [ecx], 0
.text:004689C5                jb      short loc_4689C8
.text:004689C7                retn
.text:004689C8 ; ---------------------------------------------------------------------------
.text:004689C8
.text:004689C8 loc_4689C8:                            ; CODE XREF: KiAcquireSpinLock+5 j
.text:004689C8                                        ; KiAcquireSpinLock+12 j
.text:004689C8                test    dword ptr [ecx], 1
.text:004689CE                jz      short KiAcquireSpinLock
.text:004689D0                pause   ;//空操作(rep nop)
.text:004689D2                jmp    short loc_4689C8
.text:004689D2 KiAcquireSpinLock endp
;==============================================================

;//解锁
.text:004689E0                public KiReleaseSpinLock
.text:004689E0 KiReleaseSpinLock proc near            ; CODE XREF: sub_41702E+E p
.text:004689E0                                        ; sub_4206D0+5 j ...
.text:004689E0                mov    byte ptr [ecx], 0
.text:004689E3                retn
.text:004689E3 KiReleaseSpinLock endp
;==============================================================
"
rep nop
这是一条很有趣的指令,咋一看,这只是一条空指令,但实际上这条指令可以降低CPU的运行频率,减低电的消耗量,但最重要的是,提高了整体的效率。因为这段指令执行太快的话,会生成很多读取内存变量的指令,另外的一个CPU可能也要写这个内存变量,现在的CPU经常需要重新排序指令来提高效率,如果读指令太多的话,为了保证指令之间的依赖性,CPU会以牺牲流水线 执行(pipeline)所带来的好处。从pentium 4以后,intel引进了一条pause指令,专门用于spin lock这种情况,据intel的文档说,加上pause可以提高25倍的效率!
也就是说在P4之前也许CPU 执行的是rep nop ,而P4以后则执行pause指令,虽然他们是相同的机器码. "
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pop系列指令
1.pop
说明:
将位于栈顶(SS:[esp])的字或双字弹出,放入op1,然后栈指针esp加2(对于16位操作数),或加4(对于32位操作数).
2.popa/popad (64位模式下会产生操作码异常#UD)
说明:
将栈顶的8个字或双字弹出,放入8个通用寄存器。这样,popa/popad一下子代替了8个连续的pop指令。8个通用寄存器按下列顺序存放栈顶元素:
POPA: DI,SI,BP,SP,BX,DX,CX,AX(16位操作数)
POPAD: EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX(32位操作数)
例如32的栈偏移:
if(opcode==popad)
{
 EDI=SS:[ESP+0];
 ESI=SS:[ESP+4];
 EBP=SS:[ESP+8];
 ESP=SS:[ESP+12];
 EBX=SS:[ESP+16];
 EDX=SS:[ESP+20];
 ECX=SS:[ESP+24];
 EAX=SS:[ESP+28];
 ESP=ESP+32;
}
3.POPF/POPFD/POPFQ
将当前的栈顶的数据复制到标志寄存器内,并修正栈指针。
POPF
对低16有效,I/O特权级只有在当前特权级为0时才能被替换,否则不变,也不产生异常。
中断启用标志,只有在当前特权级与当前I/O特权级相等或更高时才会改变。
POPFQ 用于64位模式
;-----------------------------------------
PUSH系列与上对应
先减栈指针esp,再赋值。注意特权级。
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SAHF
将AH被传送到标志字的低字节。(位0,2,4,6,7)
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值