当前位置:  开发笔记 > 编程语言 > 正文

汇编代码的数据结构?[研究]

如何解决《汇编代码的数据结构?[研究]》经验,为你挑选了1个好方法。

我打算创建一个优化的数据结构来保存汇编代码.这样我就可以完全负责将在这个结构上工作的优化算法.如果我可以在运行时编译.它将是一种动态执行.这可能吗?有人见过这样的东西吗?

我应该使用结构将结构链接到程序流程中.对象更好吗?

struct asm_code {
   int type;
   int value;
   int optimized;
   asm_code *next_to_execute;
 } asm_imp;

更新:我认为它会变成一个链表.

更新:我知道还有其他编译器.但这是一个军事绝密项目.所以我们不能相信任何代码.我们必须自己做这一切.

更新:好的,我想我只会生成基本的i386机器代码.但是如何在完成时跳进我的内存blob?



1> Nils Pipenbr..:

有可能的.动态代码生成甚至是软件渲染和图形等领域的主流.您可以在各种脚本语言中找到很多用法,在机器代码中动态编译字节码(.NET,Java,据我所知Perl.最近JavaScript也加入了俱乐部).

你也发现它也用在非常重数学的应用程序中,如果你打算在矩阵乘法中删除所有乘法,如果你计划进行数千次这样的乘法,那么它会有所不同.

我强烈建议您阅读代码的SSA表示.这是一种表示,其中每个基元被转换为所谓的三个操作数形式,并且每个变量仅被分配一次(因此相同的静态单一赋值形式).

您可以对此类代码运行高阶优化,并且可以直接将该代码转换为可执行代码.你不会在周末编写代码生成后端...

要了解SSA的外观,您可以尝试使用LLVM编译器.在他们的网站上,他们有一个小的"试用"小部件可以玩.您将C代码粘贴到窗口中,然后您可以获得与SSA表单相近的内容.

它的外观很简单:

让我们在C中采用这个整数平方根算法.(任意的例子,我只是采取了一些简单但非平凡的事情):

unsigned int isqrt32 (unsigned int value) 
{
    unsigned int g = 0;
    unsigned int bshift = 15;
    unsigned int b = 1<= temp) {
            g += b;
            value -= temp;
        }
        b>>=1;
    } while (bshift--);
    return g;
}

LLVM将其变为:

define i32 @isqrt32(i32 %value) nounwind  {
entry:
    br label %bb

bb:     ; preds = %bb, %entry
    %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ]      
    %b.0 = phi i32 [ 32768, %entry ], [ %tmp23, %bb ]
    %g.1 = phi i32 [ 0, %entry ], [ %g.0, %bb ]     
    %value_addr.1 = phi i32 [ %value, %entry ], [ %value_addr.0, %bb ]      
    %bshift.0 = sub i32 15, %indvar 
    %tmp5 = shl i32 %g.1, 1 
    %tmp7 = add i32 %tmp5, %b.0 
    %tmp9 = shl i32 %tmp7, %bshift.0    
    %tmp12 = icmp ult i32 %value_addr.1, %tmp9      
    %tmp17 = select i1 %tmp12, i32 0, i32 %b.0      
    %g.0 = add i32 %tmp17, %g.1     
    %tmp20 = select i1 %tmp12, i32 0, i32 %tmp9     
    %value_addr.0 = sub i32 %value_addr.1, %tmp20           
    %tmp23 = lshr i32 %b.0, 1       
    %indvar.next = add i32 %indvar, 1       
    %exitcond = icmp eq i32 %indvar.next, 16    
    br i1 %exitcond, label %bb30, label %bb

bb30:       ; preds = %bb
    ret i32 %g.0
}

我知道一开始看起来很可怕.它甚至不是纯粹的SSA表格.你对这种表现的阅读越多,它就越有意义.此外,您还将了解为什么这种表示如此广泛使用.

将所需的所有信息封装到数据结构中很容易.最后,您必须决定是否要使用枚举或字符串作为操作码名称等.

顺便说一句 - 我知道我没有给你一个数据结构,但更多的是一个正式但实用的语言,并建议在哪里进一步观察.

这是一个非常好的和有趣的研究领域.

编辑:在我忘记它之前:不要忽视.NET和Java的内置功能.这些语言允许您从程序中的字节代码或源代码进行编译并执行结果.

干杯,尼尔斯


关于编辑:如何使用代码执行二进制blob:

跳转到二进制blob是依赖于操作系统和平台的.简而言之,您可以使用指令缓存,也许您必须回写数据缓存,并且可能必须在您编写代码的内存区域上启用执行权限.

在win32上,它相对容易,因为如果将代码放在堆上,指令缓存刷新似乎就足够了.

您可以使用此存根来开始:

typedef void (* voidfunc) (void);

void * generate_code (void)
{
    // reserve some space
    unsigned char * buffer = (unsigned char *) malloc (1024);


    // write a single RET-instruction
    buffer[0] = 0xc3; 

    return buffer;
}

int main (int argc, char **args)
{
    // generate some code:
    voidfunc func = (voidfunc) generate_code();

    // flush instruction cache:
    FlushInstructionCache(GetCurrentProcess(), func, 1024);

    // execute the code (it does nothing atm)
    func();

    // free memory and exit.
    free (func);
}

推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有