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

直接读程序计数器

直接读程序计数器

九州编程 2019-12-02 08:04:20
直接读程序计数器在内核模式或其他模式下,可以直接读取Intel CPU上的程序计数器(即没有“技巧”)吗?
查看完整描述

3 回答

?
qq_笑_17

TA贡献1818条经验 获得超7个赞

不,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-12-03
?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

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

thisone: 
   mov (e)ax,thisone

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

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




查看完整回答
反对 回复 2019-12-03
?
HUX布斯

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

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

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


查看完整回答
反对 回复 2019-12-03
  • 3 回答
  • 0 关注
  • 548 浏览
慕课专栏
更多

添加回答

举报

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