1

私は WebAssembly を試していて、C で素数をブルート フォースするおもちゃのモジュールを作成しました。

extern "C" {
bool isPrime(int n) {
    for (int i = 2; i <= n; i++) {
        if (n % i == 0) return false;
    }

    return true;
}

int getPrimes() {
    int primesFound = 0;

    for (int i = 2; i < 4206969; i++) {
        if (isPrime(i)) {
            primesFound++;
        }
    }

    return primesFound;
}

}

これを Windows で emcc /O3 を使用してコンパイルすると、次のバイト ストリームが得られます。

    0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60, 
    0x0, 0x0, 0x60, 0x0, 0x1, 0x7f, 0x3, 0x3, 0x2, 0x0, 0x1, 0x5, 0x6, 0x1, 0x1, 0x80, 0x2,
    0x80, 0x2, 0x7, 0x1f, 0x3, 0x6, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2, 0x0, 0x9, 0x67,
    0x65, 0x74, 0x50, 0x72, 0x69, 0x6d, 0x65, 0x73, 0x0, 0x1, 0x6, 0x5f, 0x73, 0x74, 0x61,
    0x72, 0x74, 0x0, 0x0, 0xa, 0x4e, 0x2, 0x3, 0x0, 0x1, 0xb, 0x48, 0x1, 0x4, 0x7f, 0x41,
    0x2, 0x21, 0x0, 0x3, 0x40, 0x41, 0x2, 0x21, 0x1, 0x2, 0x40, 0x3, 0x40, 0x20, 0x0, 0x20, 
    0x1, 0x70, 0x45, 0xd, 0x1, 0x20, 0x0, 0x20, 0x1, 0x46, 0x21, 0x3, 0x20, 0x1, 0x41, 0x1,
    0x6a, 0x21, 0x1, 0x20, 0x3, 0x45, 0xd, 0x0, 0xb, 0x20, 0x2, 0x41, 0x1, 0x6a, 0x21, 0x2,
    0xb, 0x20, 0x0, 0x41, 0x1, 0x6a, 0x22, 0x0, 0x41, 0xf9, 0xe2, 0x80, 0x2, 0x47, 0xd, 0x0,
    0xb, 0x20, 0x2, 0xb, 0xb, 0xa, 0x1, 0x0, 0x41, 0x80, 0xc, 0xb, 0x3, 0xa0, 0x6, 0x50

おそらくほとんどの人には理解できないでしょうが、VSC の WASM to WAT ツールは、これが次の WASM を表していることを示唆しています。

(module
 (type $t0 (func))
 (type $t1 (func (result i32)))
 (func $_start (type $t0)
   nop)
 (func $getPrimes (type $t1) (result i32)
   (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
   i32.const 2
   local.set $l0
   loop $L0
     i32.const 2
     local.set $l1
     block $B1
       loop $L2
         local.get $l0
         local.get $l1
         i32.rem_u
         i32.eqz
         br_if $B1
         local.get $l0
         local.get $l1
         i32.eq
         local.set $l3
         local.get $l1
         i32.const 1
         i32.add
         local.set $l1
         local.get $l3
         i32.eqz
         br_if $L2
       end
       local.get $l2
       i32.const 1
       i32.add
       local.set $l2
     end
     local.get $l0
     i32.const 1
     i32.add
     local.tee $l0
     i32.const 4206969
     i32.ne
     br_if $L0
   end
   local.get $l2)
 (memory $memory 256 256)
 (export "memory" (memory 0))
 (export "getPrimes" (func $getPrimes))
 (export "_start" (func $_start))
 (data $d0 (i32.const 1536) "\a0\06P"))

別のプログラムから、次の EM_JS が呼び出されます。これは、WASM からの意図であり、javascript エンジンに WASM をコンパイルして実行するように指示します。

EM_JS(int, call_wasmBlock, (const uint8_t* wasmBlock, uint32_t length), {
    let wasmBuf = new Uint8Array(Module.HEAPU8.buffer, wasmBlock, length);
    WebAssembly.instantiate(wasmBuf)
        .then(
            obj => console.log(obj.instance.exports.getPrimes())
        );
});

次のエラーが表示されます。

Uncaught (in promise) CompileError: WebAssembly.instantiate(): unexpected section <Export> @+158

これでどこに行くべきか完全にはわかりません。ほとんどの場合、WebAssembly の制限を試しているだけです。

4

1 に答える 1