トップ «前の日記(2009-01-18) 最新 次の日記(2009-01-20)» 編集

日々の破片

著作一覧

2009-01-19

_ SWin

SWinをRuby-1.9.1-RC1で動かそうとしていろいろやっていたが、すぐさまSEGVする。で、パッチを作ったりしたのだが、良く良く雪見酒さんの日記を読んだら、7月の時点でわかっていた問題だったようだ。

dlの方法は、次々defineしていくという方法でびっくりするような、あともう少しでCで書くDSLという雰囲気。

で、別の方法について考えてみると、これの応用かなぁとか。つまり、引数としてではなく、自動変数に設定した値を引数として与えるという方法。

#include 
int x(int r, int p, int q, int a, int b, int c, int d)
{
    printf("%d, %d, %d, %d\n", a, b, c, d);
    return 0;
}
int main(int argc, char* argv[])
{
    int i;
    int a[] = { 0, 1, 2, 3, 4 };
    int (*fnc)(int[]);
    fnc = (int (*)(int[]))x;
    fnc(a);
    for (i = 0; i < sizeof(a)/sizeof(a[0]); i++)
    {
        a[i] += 10;
    }
    fnc(a);
    return 0;
}
実行すると
c:\test\farproc>acall
0, 1, 2, 3
10, 11, 12, 13

一回スタック調整用の関数を呼び出し、そこでスタックから戻りアドレスを取り出して、次に引数に与えた本来呼び出すべき関数のアドレスを取り出して、そこへ戻りアドレスを設定して、本来呼び出すべき関数のアドレスへジャンプとか。

試してみる。

#include 
#include 
int __stdcall y(int a, int b, int c, int d)
{
    printf("%d, %d, %d, %d\n", a, b, c, d);
    fflush(stdout);
    return 0;
}
__declspec(naked) int x(void* v)
{
    _asm {
        pop ebx // return
        pop eax // fn*
        push ebx
        jmp eax
    }
}
int ccaller(void* fnc, int cnt, void* args)
{
    void* p = _alloca(cnt * sizeof(int));
    memcpy(p, args, sizeof(int) * cnt);
    return x(fnc);
}
int main(int argc, char* argv[])
{
    int i;
    int a[] = { 0, 1, 2, 3, 4, 5 };
    ccaller(y, 4, a);
    for (i = 0; i < sizeof(a)/sizeof(a[0]); i++)
    {
        a[i] += 10;
    }
    ccaller(y, 4, a);
    return 0;
}

さて、うまく動いているようだが。

c:\test>cl bcall.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
 
bcall.c
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
 
/out:bcall.exe
bcall.obj
 
c:\test>bcall
0, 1, 2, 3
10, 11, 12, 13

問題は__declspec(naked)でフレームを作らないようにしているわけだが、他の処理系で使えるのかなぁ。逆に作らせるようにして、espで調整するというのもありだろうが、最適化フラグいじったとたんになくなったりするかも知れないのが問題。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|

ジェズイットを見習え