【问题标题】:Reset the program-counter (AKA instruction-pointer) to 0将程序计数器(AKA 指令指针)重置为 0
【发布时间】:2014-08-13 17:56:39
【问题描述】:

我正在尝试将程序计数器(AKA 指令指针)重置为 0。

我曾预计以下 C 代码可以工作(但它没有):

typedef void(*func)();
func reset = NULL;
reset();

下面是使用VS2013编译器时的反汇编:

mov  dword ptr[reset],0
mov  esi,esp
call dword ptr[reset]

我意识到这个问题不是由 C 语言标准规定的,而是特定编译器实现的问题。尽管如此,我希望它几乎可以在每个体面的编译器上工作。

除了将 PC/IP 设置为该函数的地址之外,函数调用还可以编译成什么?

谢谢

【问题讨论】:

  • 你期望它做什么?我预计那会崩溃。
  • @dohashi:崩溃没有问题,但我希望看到 PC 寄存器在崩溃前被设置为 0。
  • 你在实践中观察到了什么?
  • 在汇编程序中执行此类操作的标准方法是 push 0; ret; 。 IIRC,一些处理器在开机时或中断后以 IP=0 启动。
  • 您的代码导致我的$pc 归零...

标签: c compiler-construction compilation program-counter


【解决方案1】:

这实际上取决于您的目标硬件,但它可能会编译为与任何其他函数指针调用相同的东西。编译器也可以识别给reset 的常量值,并对其进行优化。如果不出意外,你总是可以这样做:

((void (*)())NULL)();

基本上将NULL 转换为void 类型的无参数函数。


调用是否成功是完全不同的事情:在大多数使用虚拟内存的平台上,内核故意留下NULL 地址+ 一些未映射的空间(可能是几KB,也可能是几MB)。您的指令指针可能仍会变为 0,但一旦 CPU 尝试从该地址获取指令,KABOOM

【讨论】:

  • 我已经检查了优化问题,编译器没有“大惊小怪”...
  • 哦,一直都是你……甚至都没注意到……谢谢:)
猜你喜欢
  • 1970-01-01
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 2015-05-09
  • 2014-07-30
  • 2016-06-16
  • 1970-01-01
相关资源
最近更新 更多