MessageBox(3,3,3,3)
これをコパイルしてexeを出す。このexeをdumpbin.exeで逆アセンブルする。
すると…

00401000: 55 push ebp
00401001: E8 04 0E 00 00 call 00401E0A
00401006: 6A 00 push 0
00401008: E8 AC 14 00 00 call 004024B9
0040100D: A3 4C 56 40 00 mov dword ptr ds:[0040564Ch],eax
00401012: 6A 00 push 0
00401014: E8 A0 14 00 00 call 004024B9
00401019: A3 50 56 40 00 mov dword ptr ds:[00405650h],eax
0040101E: 6A 00 push 0
00401020: E8 94 14 00 00 call 004024B9
00401025: A3 54 56 40 00 mov dword ptr ds:[00405654h],eax
0040102A: 6A 00 push 0
0040102C: E8 88 14 00 00 call 004024B9
00401031: A3 58 56 40 00 mov dword ptr ds:[00405658h],eax
00401036: 6A 00 push 0
00401038: E8 7C 14 00 00 call 004024B9
0040103D: A3 5C 56 40 00 mov dword ptr ds:[0040565Ch],eax
00401042: 6A 00 push 0
00401044: E8 70 14 00 00 call 004024B9
00401049: A3 60 56 40 00 mov dword ptr ds:[00405660h],eax
0040104E: 6A 00 push 0
00401050: E8 64 14 00 00 call 004024B9
00401055: A3 64 56 40 00 mov dword ptr ds:[00405664h],eax
0040105A: 6A 00 push 0
0040105C: E8 58 14 00 00 call 004024B9
00401061: A3 68 56 40 00 mov dword ptr ds:[00405668h],eax
00401066: 6A 00 push 0
00401068: E8 4C 14 00 00 call 004024B9
0040106D: A3 6C 56 40 00 mov dword ptr ds:[0040566Ch],eax
00401072: 6A 00 push 0
00401074: E8 40 14 00 00 call 004024B9
00401079: A3 70 56 40 00 mov dword ptr ds:[00405670h],eax
0040107E: 6A 00 push 0
00401080: E8 34 14 00 00 call 004024B9
00401085: A3 74 56 40 00 mov dword ptr ds:[00405674h],eax
0040108A: 6A 00 push 0
0040108C: E8 28 14 00 00 call 004024B9
00401091: A3 78 56 40 00 mov dword ptr ds:[00405678h],eax
00401096: 6A 00 push 0
00401098: E8 1C 14 00 00 call 004024B9
0040109D: A3 7C 56 40 00 mov dword ptr ds:[0040567Ch],eax
004010A2: 6A 00 push 0
004010A4: E8 10 14 00 00 call 004024B9
004010A9: A3 80 56 40 00 mov dword ptr ds:[00405680h],eax
004010AE: 6A 00 push 0
004010B0: E8 04 14 00 00 call 004024B9
004010B5: A3 84 56 40 00 mov dword ptr ds:[00405684h],eax
004010BA: 6A 00 push 0
004010BC: E8 F8 13 00 00 call 004024B9
004010C1: A3 88 56 40 00 mov dword ptr ds:[00405688h],eax
004010C6: 6A 00 push 0
004010C8: E8 EC 13 00 00 call 004024B9
004010CD: A3 8C 56 40 00 mov dword ptr ds:[0040568Ch],eax
004010D2: 6A 00 push 0
004010D4: E8 E0 13 00 00 call 004024B9
004010D9: A3 90 56 40 00 mov dword ptr ds:[00405690h],eax
004010DE: 6A 00 push 0
004010E0: E8 D4 13 00 00 call 004024B9
004010E5: A3 94 56 40 00 mov dword ptr ds:[00405694h],eax
004010EA: 6A 00 push 0
004010EC: E8 C8 13 00 00 call 004024B9
004010F1: A3 98 56 40 00 mov dword ptr ds:[00405698h],eax
004010F6: 6A 00 push 0
004010F8: E8 BC 13 00 00 call 004024B9
004010FD: A3 9C 56 40 00 mov dword ptr ds:[0040569Ch],eax
00401102: 6A 00 push 0
00401104: E8 B0 13 00 00 call 004024B9
00401109: A3 A0 56 40 00 mov dword ptr ds:[004056A0h],eax
0040110E: 6A 00 push 0
00401110: E8 A4 13 00 00 call 004024B9
00401115: A3 A4 56 40 00 mov dword ptr ds:[004056A4h],eax
0040111A: 6A 00 push 0
0040111C: E8 98 13 00 00 call 004024B9
00401121: A3 A8 56 40 00 mov dword ptr ds:[004056A8h],eax
00401126: 6A 00 push 0
00401128: E8 8C 13 00 00 call 004024B9
0040112D: A3 AC 56 40 00 mov dword ptr ds:[004056ACh],eax
00401132: 6A 00 push 0
00401134: E8 80 13 00 00 call 004024B9
00401139: A3 B0 56 40 00 mov dword ptr ds:[004056B0h],eax
0040113E: 6A 00 push 0
00401140: E8 74 13 00 00 call 004024B9
00401145: A3 B4 56 40 00 mov dword ptr ds:[004056B4h],eax
0040114A: 6A 00 push 0
0040114C: E8 68 13 00 00 call 004024B9
00401151: A3 B8 56 40 00 mov dword ptr ds:[004056B8h],eax
00401156: 6A 00 push 0
00401158: E8 5C 13 00 00 call 004024B9
0040115D: A3 BC 56 40 00 mov dword ptr ds:[004056BCh],eax
00401162: 6A 00 push 0
00401164: E8 50 13 00 00 call 004024B9
00401169: A3 C0 56 40 00 mov dword ptr ds:[004056C0h],eax
0040116E: 6A 00 push 0
00401170: E8 44 13 00 00 call 004024B9
00401175: A3 C4 56 40 00 mov dword ptr ds:[004056C4h],eax
0040117A: 6A 00 push 0
0040117C: E8 38 13 00 00 call 004024B9
00401181: A3 C8 56 40 00 mov dword ptr ds:[004056C8h],eax
00401186: 6A 03 push 3
00401188: 6A 03 push 3
0040118A: 6A 03 push 3
0040118C: 6A 03 push 3
0040118E: FF 15 9E 31 40 00 call dword ptr ds:[0040319Eh]
00401194: E8 EE 10 00 00 call 00402287
00401199: 33 C0 xor eax,eax
0040119B: 5D pop ebp
0040119C: C3 ret
0040119D: 81 EC 00 00 00 00 sub esp,0
004011A3: 55 push ebp
004011A4: 8B EC mov ebp,esp
004011A6: 53 push ebx
004011A7: 56 push esi
004011A8: 57 push edi
004011A9: FF B5 08 00 00 00 push dword ptr [ebp+00000008h]
004011AF: 6A 00 push 0
004011B1: FF 35 30 50 40 00 push dword ptr ds:[00405030h]
004011B7: FF 15 6E 31 40 00 call dword ptr ds:[0040316Eh]
004011BD: 5F pop edi
004011BE: 5E pop esi
004011BF: 5B pop ebx
004011C0: 8B E5 mov esp,ebp
004011C2: 5D pop ebp
004011C3: 83 C4 00 add esp,0
004011C6: C2 04 00 ret 4
004011C9: 81 EC 04 00 00 00 sub esp,4
004011CF: 55 push ebp
004011D0: 8B EC mov ebp,esp
004011D2: 53 push ebx
004011D3: 56 push esi
004011D4: 57 push edi
004011D5: 6A 00 push 0
004011D7: 6A 04 push 4
004011D9: 8B C5 mov eax,ebp
004011DB: 05 04 00 00 00 add eax,4
004011E0: 50 push eax
004011E1: FF 15 86 31 40 00 call dword ptr ds:[00403186h]
004011E7: FF B5 0C 00 00 00 _push dword ptr [ebp+0000000Ch]
(以下略)
こんな事になる。
自分のつくた部分はどこだろう?
正解は00401186hから5行である。

先頭からアセンブラが記述されていないのは、COFF形式のEXEファイルに従っている為セクションが異なる。

ab4は直接EXE形式を出力するコンパイラで、実行形式はMicrosoftのCOFF形式のEXEファイルである。
ここに示されているアドレス0x4011E0等は、VirtualAddressで物理アドレスではない。
Windowsは仮想記憶をサポートしているので、出力される実行形式のアドレスは仮想記憶を介している点に注意。

ab4の出力を良く観察すると、変数や関数の引数はすべてスタック操作が関与している事が伺える。
従ってBASICの式や構文上に現れる変数の取り扱いは、実際のCPUレベルでは主記憶メモリに置かれたスタック
に記録されているという事。
これはBASICのコードがコンパイルされる際に、一旦中間言語にコンパイルされ、コードジェネレータが
x86のアセンブラを生成する事と関係しているかもしれない。
なお、変数をスタックに配置する方法は一般的に行われる。

変数に代入/参照する際にはやや煩雑なスタック操作が生成されるため、命令が重複したアセンブラコードが出力されている。
最適化は行われていない様子。


最適化手法

  • ループ内で計算結果が変わらないものは外に出す
  • ループ回数を減らす
  • 分岐を減らす
  • 並列化

SIMD

Cでコードを書いてDLにする。

#include <emmintrin.h>

enum {
ADD=0,
SUB,
MUL
};

void _stdcall simd(int *r0, int *r1, int mode){
__m128i m[2];

m[0] = _mm_loadu_si128((__m128i*)r0);
m[1] = _mm_loadu_si128((__m128i*)r1);
switch (mode) {
default:
break;
case ADD:
m[0] = _mm_add_epi32(m[0], m[1]);
break;
case SUB:
m[0] = _mm_sub_epi32(m[0], m[1]);
break;
case MUL:
m[0] = _mm_mul_epu32(m[0], m[1]);
break;
}
_mm_storeu_si128((__m128i*)r0, m[0]);
return;
}
これをABで呼び出す。

#N88BASIC
Declare Sub simd Lib"s2.dll"(r0 As *Long, r1 As *Long,mode As Long)
Enum
ADDi = 0
SUBi
MULi
End Enum

Dim r0[3] As Long,r1[3] As Long
Dim n As Long
For n=0 To 3
r0[n] = n+1
r1[n]=r0[n]*10
Next

simd(r0,r1,ADDi)
For n=0 To 3
Print r0[n];" ";
Next
Print

simd(r0,r1,SUBi)
For n=0 To 3
Print r0[n];" ";
Next
Print

simd(r0,r1,MULi)
For n=0 To 3
Print r0[n];" ";
Next
Print

またはメモリ上の機械語プログラムの応用でABに組み入れてもいいかも