猿问

直接读程序计数器

直接读程序计数器

在内核模式或其他模式下,可以直接读取Intel CPU上的程序计数器(即没有“技巧”)吗?



达令说
浏览 508回答 3
3回答

慕尼黑5688855

不,EIP / IP无法直接访问,但在位置相关的代码中,它是一个链接时间常量,因此您可以使用附近(或远程)符号作为立即数。   mov eax, nearby_label    ; in position-dependent codenearby_label:要使位置无关的32位代码获得EIP或IP:        call _here_here:  pop eax; eax now holds the PC.在比Pentium Pro(或可能是PIII)更新的CPU上,call rel32rel32 = 0是特殊的,不会影响返回地址预测器堆栈。因此,这在现代x86上既高效又紧凑,是clang用于32位位置无关代码的。在旧的32位Pentium Pro CPU上,这会使调用/返回预测器堆栈失去平衡,因此更喜欢调用实际返回的函数,以避免ret在父函数中最多15个左右的指令错误预测。(除非你不会返回,或者很少这样做无关紧要。)但是,返回地址预测器堆栈将会恢复。get_retaddr_ppro:     mov  eax, [esp]     ret                ; keeps the return-address predictor stack balanced                        ; even on CPUs where  call +0 isn't a no-op.在x86-64模式下,可以使用RIP相关直接读取RIPlea。default rel           ; NASM directive: use RIP-relative by defaultlea  rax, [_here]     ; RIP + 0_here:MASM或GNU .intel_syntax:lea  rax, [rip]AT&T语法: lea 0(%rip), %rax

隔江千里

如果您需要特定指令的地址,通常这样的方法就可以了:thisone:     mov (e)ax,thisone(注意:在某些汇编程序中,这可能是错误的并从[thisone]中读取一个单词,但通常会有一些语法让汇编程序做正确的事情。)如果您的代码静态加载到特定地址,汇编程序已经知道(如果您告诉它正确的起始地址)所有指令的绝对地址。动态加载的代码,例如作为任何现代操作系统上的应用程序的一部分,将通过动态链接器完成的地址重定位获得正确的地址(假设汇编器足够智能以生成重定位表,它们通常是这样)。

慕侠2389804

在x86-64上你可以这样做:lea rax,[rip] (48 8d 05 00 00 00 00)
随时随地看视频慕课网APP
我要回答