【问题标题】:executing assembly code in c在c中执行汇编代码
【发布时间】:2012-10-23 20:00:49
【问题描述】:

我想知道是否可以调用 .c 汇编代码? 我想把这段代码放在我的 .c 文件中

我想在.c文件中执行的汇编代码以返回地址

1. mov eax, 0x2d
2. mov ebx, 0
3. int 0x80

我知道答案是 eax。

这是.c文件的一部分:

1. void function(void)
2. {
3. void *sp;
4. sp = eax;
5. fprintf(stderr, "system break:   %p\n", sp);
6. }

我该怎么做?

【问题讨论】:

  • 您使用的是哪个 C 编译器?
  • C代码应该做什么,eax中的值是什么,sp是什么?
  • @hyde 我正在使用 gcc 而 sp 只是一个变量,并且想要这样做,fprintf(stderr, "system break: %p\n", sp);当我有 sp,并且 sp 有 eax 值时,eax 中的值类似于 0x99ae000

标签: c assembly nasm


【解决方案1】:

您真的需要将 Nasm 语法中的 asm 源代码“放入”您的 C 源程序吗?弗格编辑。 lcc 也许......如果你想从你的 C 程序中“执行”你的 asm 程序......

    global getbrk
    section .text
    getbrk:
        push ebx ; C likes it saved
        mov eax, 45 ; __NR_brk
        xor ebx, ebx ; get current break
        int 80h
        pop ebx
        ret

组装nasm -f elf getbrk.asm,将sp=getbrk();放入你的C文件,编译gcc -m32 -O3 -o myprog myprog.c getbrk.o

或者只是在你的 C 程序中 sp=sbrk(0); 并跳过 asm...不会比使用 int 80h 更便携。 (但那会有什么乐趣呢?):)

【讨论】:

  • 问题的关键在于我没有/或可能不会在我的 c 程序中使用 sp = sbrk(0);但无论如何,谢谢。而且我认为您的解决方案也会奏效。
【解决方案2】:
void function(void){

   void *sp
   __asm__ volatile(
   "movl $0x2d, %%eax;"
   "movl $0, %%ebx;"
   "int $0x80"
   :"=a"(sp)
   :
   :"%ebx"
   );

   fprintf(stderr, "system break: %p\n",sp);
   }

这是我的答案:)

【讨论】:

  • 您通常希望使用输入约束来让编译器在"int $0x80" 模板周围的寄存器中设置正确的值,但是这是安全的。对于某些系统调用,您需要一个"memory" clobber,但是这个不传递任何指针,因此不需要内存同步。无论如何,asm volatile("int $0x80" : "=a"(sp) : "a"(__NR_brk), "b"(0)); 会是一个不错的选择。
【解决方案3】:

执行此操作的能力是特定于编译器的。 Gcc 允许 using its asm keyword extension,而 Visual Studio 实现 different extension

请注意,除了不可移植到其他体系结构的明显问题之外,包括任何内联汇编都会降低性能,因为编译器无法分析汇编来确定它是否无副作用、内联是否安全、是否访问全局资源等等。

【讨论】:

【解决方案4】:

另一种方法,例如使用gcc,就是先编译一些很琐碎的函数,不做优化:

int foo(int a, int b) {
  return a+(b<<3);
}

gcc -S foo.c

并使用 foo.s 作为模板。稍后可以编译并链接这些文件 gcc main.c foo.s(并确保删除 foo.c 文件/将 foo.s 重命名为其他内容)

从那个特定的函数可以观察到,编译器将结果放在哪里,以及编译器将第一个和第二个参数放在哪个地址或寄存器中。

这比使用读、写、破坏列表学习 asm 模板要快一些。

【讨论】:

  • 这是一个不错的建议,但 OP 非常明确地表示要将程序集 放入 他们的 C 源文件中。
【解决方案5】:

一些编译器将__asm__asm 关键字实现为C 语言的扩展:

__asm__(
    "mov eax, 0x2d\n"
    "mov ebx, 0\n"
    "int 0x80\n"
);

括号中的代码将被逐字复制到汇编程序的输入中。有关 GCC 如何实现此功能的更多文档,请参见 here

顺便说一句,如果你想改变堆栈指针的值(为什么?),你可以一行完成:

__asm__("mov esp, eax");

【讨论】:

  • 我认为这里的sp只是C变量名,与栈指针无关。
  • @hyde 很有可能 :) 但是,当上下文是“内联汇编”和“void *sp = eax;”时,请原谅我的这种假设 :)
  • 我现在如何调用该函数,以便 sp = 返回? sp = asm("asm 代码"); ???
  • @WeigelGram 不,但是如果您阅读了我提供的链接中的文档,您就会知道。
  • @WeigelGram 相信你一定要写__asm("mov %%eax, 0x222" : "+r"(sp));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-27
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
相关资源
最近更新 更多