为了账号安全,请及时绑定邮箱和手机立即绑定

直接读程序计数器

直接读程序计数器

达令说 2019-11-03 08:04:47
直接读程序计数器在内核模式或其他模式下,可以直接读取Intel CPU上的程序计数器(即没有“技巧”)吗?
查看完整描述

3 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

不,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_syntaxlea  rax, [rip]

AT&T语法: lea 0(%rip), %rax



查看完整回答
反对 回复 2019-11-04
?
隔江千里

TA贡献1906条经验 获得超10个赞

如果您需要特定指令的地址,通常这样的方法就可以了:

thisone: 
   mov (e)ax,thisone

(注意:在某些汇编程序中,这可能是错误的并从[thisone]中读取一个单词,但通常会有一些语法让汇编程序做正确的事情。)

如果您的代码静态加载到特定地址,汇编程序已经知道(如果您告诉它正确的起始地址)所有指令的绝对地址。动态加载的代码,例如作为任何现代操作系统上的应用程序的一部分,将通过动态链接器完成的地址重定位获得正确的地址(假设汇编器足够智能以生成重定位表,它们通常是这样)。



查看完整回答
反对 回复 2019-11-04
?
慕侠2389804

TA贡献1719条经验 获得超6个赞

在x86-64上你可以这样做:

lea rax,[rip] (48 8d 05 00 00 00 00)


查看完整回答
反对 回复 2019-11-04
  • 3 回答
  • 0 关注
  • 459 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信