C语言中如何将程序跳转到指定地址?

发布于 2024-12-16 12:19:29 字数 116 浏览 0 评论 0原文

我希望程序跳转到内存中的特定地址并从该地址继续执行。我考虑过使用 goto 但我没有标签,而只是内存中的地址。

无需担心从跳转地址返回。

编辑:使用GCC编译器

I want the program to jump to a specific address in memory and continue execution from that address. I thought about using goto but I don't have a label rather just an address in memory.

There is no need to worry about return back from the jump address.

edit: using GCC compiler

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

明明#如月 2024-12-23 12:19:29

内联汇编可能是最简单、最“优雅”的解决方案,尽管这样做非常不寻常,除非您正在编写调试器或一些专门的内省系统。

另一种选择可能是声明一个指向 void 函数的指针 (void (*foo)(void)),然后将指针设置为包含您的地址,然后调用它:

void (*foo)(void) = (void (*)())0x12345678;
foo();

将会有东西被推送堆栈,因为编译器认为您正在执行子例程调用,但由于您不关心返回,所以这可能会起作用。

Inline assembly might be the easiest and most "elegant" solution, although doing this is highly unusual, unless you are writing a debugger or some specialized introspective system.

Another option might be to declare a pointer to a void function (void (*foo)(void)), then set the pointer to contain your address, and then invoke it:

void (*foo)(void) = (void (*)())0x12345678;
foo();

There will be things pushed on the stack since the compiler thinks you are doing a subroutine call, but since you don't care about returning, this might work.

夜司空 2024-12-23 12:19:29

gcc 有一个允许跳转到任意地址的扩展:

void *ptr = (void *)0x1234567;  // a random memory address
goto *ptr;                      // jump there -- probably crash

这与使用设置为固定值的函数指针几乎相同,但它实际上会使用跳转指令而不是调用指令(因此堆栈不会待修改)

gcc has an extension that allows jumping to an arbitrary address:

void *ptr = (void *)0x1234567;  // a random memory address
goto *ptr;                      // jump there -- probably crash

This is pretty much the same as using a function pointer that you set to a fixed value, but it will actually use a jump instruction rather than a call instruction (so the stack won't be modified)

走过海棠暮 2024-12-23 12:19:29
#include <stdio.h>
#include <stdlib.h>

void go(unsigned int addr) {
  (&addr)[-1] = addr;
}

int sub() {
  static int i;
  if(i++ < 10) printf("Hello %d\n", i);
  else exit(0);
  go((unsigned int)sub);
}

int main() {
  sub();
}

当然,这会调用未定义的行为,与平台相关,假设代码地址与 int 大小相同,等等。

#include <stdio.h>
#include <stdlib.h>

void go(unsigned int addr) {
  (&addr)[-1] = addr;
}

int sub() {
  static int i;
  if(i++ < 10) printf("Hello %d\n", i);
  else exit(0);
  go((unsigned int)sub);
}

int main() {
  sub();
}

Of course, this invokes undefined behavior, is platform-dependent, assumes that code addresses are the same size as int, etc, etc.

一梦浮鱼 2024-12-23 12:19:29

它应该看起来像这样:

unsigned long address=0x80; 

void (*func_ptr)(void) = (void (*)(void))address;
func_ptr();

但是,这不是一个非常安全的操作,跳转到某个未知的地址可能会导致崩溃!

It should look something like this:

unsigned long address=0x80; 

void (*func_ptr)(void) = (void (*)(void))address;
func_ptr();

However, it is not a very safe operation, jumping to some unknown address will probably result in a crash!

是伱的 2024-12-23 12:19:29

由于问题具有 C++ 标签,因此这里是一个 C++ 调用具有 main()--int main(int argc, char* argv[])< 等签名的函数的示例/代码>:

int main(int argc, char* argv[])
{
    auto funcAddr = 0x12345678; //or use &main...
    auto result = reinterpret_cast<int (*)(int, char**)>(funcAddr)(argc, argv);
}

Since the question has a C++ tag, here's an example of a C++ call to a function with a signature like main()--int main(int argc, char* argv[]):

int main(int argc, char* argv[])
{
    auto funcAddr = 0x12345678; //or use &main...
    auto result = reinterpret_cast<int (*)(int, char**)>(funcAddr)(argc, argv);
}
做个ˇ局外人 2024-12-23 12:19:29

您是否可以控制要跳转到的地址处的代码?这是C还是C++?

如果您使用 C 并且可以在需要跳回的地方运行 setjmp() ,我犹豫地建议 setjmp() / longjmp() 。话虽这么说,你必须非常小心地对待这些。

对于 C++,请参阅以下有关 longjmp() 快捷方式异常处理和析构函数的讨论。这会让我更加犹豫是否建议在 C++ 中使用它。

C++:可以安全地使用 longjmp 和 setjmp 吗?

Do you have control of the code at the address that you intend to jump to? Is this C or C++?

I hesitantly suggest setjmp() / longjmp() if you're using C and can run setjmp() where you need to jump back to. That being said, you've got to be VERY careful with these.

As for C++, see the following discussion about longjmp() shortcutting exception handling and destructors destructors. This would make me even more hesitant to suggest it's use in C++.

C++: Safe to use longjmp and setjmp?

青衫负雪 2024-12-23 12:19:29

这就是我用于引导加载程序的内容(MSP430AFE253,Compiler = gcc,CodeCompeserStudio);

#define API_RESET_VECT 0xFBFE
#define JUMP_TO_APP()  {((void (*)()) (*(uint16_t*)API_RESET_VECT)) ();}

This is what I am using for my bootstrap loader(MSP430AFE253,Compiler = gcc,CodeCompeserStudio);

#define API_RESET_VECT 0xFBFE
#define JUMP_TO_APP()  {((void (*)()) (*(uint16_t*)API_RESET_VECT)) ();}
浴红衣 2024-12-23 12:19:29

我建议这个代码:

asm(
"LDR R0,=0x0a0000\n\t" /* Or 0x0a0000 for the base Addr. */
"LDR R0, [R0, #4]\n\t" /* Vector+4 for PC */
"BX R0"
);

I Propos this code:

asm(
"LDR R0,=0x0a0000\n\t" /* Or 0x0a0000 for the base Addr. */
"LDR R0, [R0, #4]\n\t" /* Vector+4 for PC */
"BX R0"
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文