【问题标题】:generating simplest binary code obj file生成最简单的二进制代码 obj 文件
【发布时间】:2014-08-27 21:51:40
【问题描述】:

我需要生成一些包含我的二进制文件的简单 obj/o 文件 程序体(我需要写一些非常简单的部分汇编程序)

我需要生成这样的 obj 二进制文件,以便我可以使用一些链接器来链接并运行我的程序。我想知道 1)什么是最简单的obj格式(我需要一些可以最终与gcc链接的东西,但如果有人认为更容易的话,据我所知,有一些工具可以将一种obj格式转换为另一种格式,所以我可以使用thic转换器) 2)我想知道生成这个 obj 上下文的代码会是什么样子 - 假设我有二进制 asm 内容要刷新,但我只需要在它周围制作 obj“信封”

我什至不需要刷新多个程序(只需一个就足够了,在这种情况下,我可以为每个程序生成单独的 obj),但我还想要一些代码来嵌入我导出的程序符号名称并嵌入导入符号的名称(尽管它可能也不是那么重要,因为我可以通过参数传递它们_我主要对允许我运行它的极端简单性感兴趣

假设我已经说过要刷新的数据

const int procedure_binary_body_max = 130;

char procedure_binary_body[procedure_binary_body_max]; //130 bytes of procedure body
char* procedure_symbol_name = "sse_dot";

我需要一些代码来制作并将其作为 obj 文件保存到我可以链接的磁盘 它与 gcc

有人可以帮忙吗?非常tnx

【问题讨论】:

  • 不会是编写翻译器而不是部分汇编器的方法吗?翻译器只需将您的输入翻译成汇编源代码,然后按照惯例将其汇编成可链接的目标文件。
  • 不,需要生成 obj,但可以尽可能简单 - 它不应该太难,但一些官方文档让我害怕,需要一些更有用的提示 /sn-p 或其他东西
  • 汇编器可以从你翻译的源代码生成对象

标签: gcc assembly compiler-construction linker x86


【解决方案1】:

注意:以下适用于 amd64 上的 linux,但同样的原理也适用于 i386。

如果调用外部工具(在本例中为 gcc 和 nasm)没有问题,您可以这样做:

main.c:

#include <stdio.h>
#include <unistd.h>

void make_obj (const char *filename,
               const char *data,
               size_t length,
               const char *entry_point)
{
    const char *filename_s = "tmp.s";
    const char *filename_bin = "tmp.bin";

    FILE *f;
    char buf[1000];

    // create bin file
    f = fopen (filename_bin, "wb");
    fwrite (data, 1, length, f);
    fclose (f);

    // create assembly wrapper
    f = fopen (filename_s, "w");
    fprintf (f,
             "\t\tsection .text\n"
             "\t\tglobal %s\n"
             "%s:\n"
             "\t\tincbin \"%s\"\n",
             entry_point, entry_point, filename_bin);
    fclose (f);

    // call nasm to convert it to object file
    snprintf (buf, 1000, "nasm -f elf64 -o %s %s", filename, filename_s);
    system (buf);

    unlink (filename_bin);
    unlink (filename_s);
}

void test_add (const char *filename_o, const char *entry_point)
{
    const char *filename_c = "test.c";
    const char *filename_exe = "test";

    FILE *f;
    char buf[1000];

    f = fopen (filename_c, "w");
    fprintf (f,
             "#include <stdio.h>\n"
             "\n"
             "extern int %s (int a, int b);\n"
             "\n"
             "int main () {\n"
             "\tconst int a = 2;\n"
             "\tconst int b = 3;\n"
             "\n"
             "\tint c = %s (a, b);\n"
             "\n"
             "\tprintf (\"%%d + %%d = %%d\\n\", a, b, c);\n"
             "\n"
             "\treturn 0;\n"
             "}\n",
             entry_point, entry_point);
    fclose (f);

    snprintf (buf, 1000, "gcc -o %s %s %s",
              filename_exe, filename_c, filename_o);
    system (buf);

    snprintf (buf, 1000, "./%s", filename_exe);
    system (buf);

    unlink (filename_c);
    unlink (filename_exe);
}

int main ()
{
    const char code[] = {
        0x48, 0x89, 0xF8,            // mov rax,rdi
        0x48, 0x01, 0xF0,            // add rax,rsi
        0xC3                         // ret
    };

    const char *filename_o = "tmp.o";
    const char *entry_point = "add";

    make_obj (filename_o, code, sizeof(code), entry_point);
    test_add (filename_o, entry_point);
    unlink (filename_o);

    return 0;
}

测试它:

cc -o main main.c
./main

如果一切顺利,main 应该生成一个包含整数加法函数的机器代码的目标文件,一个调用机器代码例程的 C 文件,编译 C 文件并运行它。

结果应该是:

2 + 3 = 5

注释掉 unlink() 调用以保留中间文件。

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    相关资源
    最近更新 更多