乗算・除算をインラインアセンブラで記述したものを作成しました。『独習アセンブラ 新版』に GCC のインラインアセンブラの書き方が説明されています。
#define USE_X68000
で X68000 版を作ることができます。最初は起動できなかったのですが、実行ファイルのサイズを削減するためのコンパイルのオプションを取り除くと起動できました。実行ファイルのサイズは 958 KB あります。これは今後調査の必要があります。
乗算・除算をインラインアセンブラで記述するサンプル
を切り替えることができます。Visual Studio ではインラインアセンブラを使うことが難しいようなのでインラインアセンブラは使っていません。
使い方
16 ビットの符号なし整数の乗算・除算を行います。
- 「数値 * 数値」で乗算
- 「数値 / 数値」で除算
を行います。間違った入力をすると終了します。
#include <iostream> #include <string> #define BITRANGE 16 //#define USE_WINGCC //#define USE_X68000 //int multiply2(int x, int y, int bitsize) #ifdef USE_X68000 asm( "shift_multiply_a:\n\t" "move.l 8(%sp), %d1\n\t" "move.w #16, %a0\n\t" "moveq #0, %d0\n\t" "smulL3:\n\t" "add.l %d1, %d1\n\t" "add.l %d0, %d0\n\t" "btst #16, %d1\n\t" "jeq smulL2\n\t" "add.l 4(%sp), %d0\n\t" "smulL2:\n\t" "subq.l #1, %a0\n\t" "cmp.w #0, %a0\n\t" "jne smulL3\n\t" "rts\n\t" ); int shift_multiply(int x, int y) { int result = 0; asm( "move.l %1, -(%%sp)\n\t" "move.l %2, -(%%sp)\n\t" "jsr shift_multiply_a\n\t" "add.l #8, %%sp\n\t" "move.l %%d0, %0\n\t" : "=r"(result) : "r"(x), "r"(y) : "d0", "d0", "a0", "a1" ); return result; } #else #ifdef USE_WINGCC asm( "shift_multiply_a:\n\t" "movl $16, %r8d\n\t" "xorl %eax, %eax\n\t" "smulL3:\n\t" "addl %edx, %edx\n\t" "addl %eax, %eax\n\t" "btl $16, %edx\n\t" "jnc smulL2\n\t" "addl %ecx, %eax\n\t" "smulL2:\n\t" "decl %r8d\n\t" "jne smulL3\n\t" "ret\n\t" ); int shift_multiply(int x, int y) { int result = 0; asm( "call shift_multiply_a\n\t" : "=a"(result) : "c"(x), "d"(y) : "r8" ); return result; } #else int shift_multiply(int x, int y) { int c = 1 << BITRANGE; int result = 0; for (int i = 0; i < BITRANGE; i++) { y <<= 1; result <<= 1; if (y & c) { result += x; } } return result; } #endif #endif int test_multiply(int x, int y) { return shift_multiply(x, y); } //int divide1(int x, int y, int bitsize) #ifdef USE_X68000 asm( "shift_divide_a:\n\t" "move.l 4(%sp), %a1\n\t" "move.l 8(%sp), %d1\n\t" "swap %d1\n\t" "clr.w %d1\n\t" "move.w #16, %a0\n\t" "moveq #0, %d0\n\t" "sdivL10:\n\t" "asr.l #1, %d1\n\t" "add.l %d0, %d0\n\t" "cmp.l %d1, %a1\n\t" "jlt sdivL9\n\t" "addq.l #1, %d0\n\t" "sub.l %d1, % a1\n\t" "sdivL9:\n\t" "subq.l #1, %a0\n\t" "cmp.w #0, %a0\n\t" "jne sdivL10\n\t" "rts\n\t" ); int shift_divide(int x, int y) { int result = 0; asm( "move.l %1, -(%%sp)\n\t" "move.l %2, -(%%sp)\n\t" "jsr shift_divide_a\n\t" "add.l #8, %%sp\n\t" "move.l %%d0, %0\n\t" : "=r"(result) : "r"(x), "r"(y) : "d0", "d0", "a0", "a1" ); return result; } #else #ifdef USE_WINGCC asm( "shift_divide_a:\n\t" "movl $16, %r8d\n\t" "xorl %eax, %eax\n\t" "sall $16, %edx\n\t" "sdivL12:\n\t" "sarl %edx\n\t" "addl %eax, %eax\n\t" "cmpl %ecx, %edx\n\t" "jg sdivL11\n\t" "incl %eax\n\t" "subl %edx, %ecx\n\t" "sdivL11:\n\t" "decl %r8d\n\t" "jne sdivL12\n\t" "ret\n\t" ); int shift_divide(int x, int y) { int result = 0; asm( "call shift_divide_a\n\t" : "=a"(result) : "c"(x), "d"(y) : "r8" ); return result; } #else int shift_divide(int x, int y) { int result = 0; y <<= BITRANGE; for (int i = 0; i < BITRANGE; i++) { y >>= 1; result <<= 1; if (x >= y) { result++; x -= y; } } return result; } #endif #endif int test_divide(int x, int y) { return shift_divide(x, y); } int main() { std::cout << "Start" << std::endl; for (;;) { std::cout << "input exp> "; int x, y; std::string op; std::cin >> x >> op >> y; if (op == "*") { int result_multiply = test_multiply(x, y); std::cout << "Multiply: " << result_multiply << std::endl; } else if (op == "/") { int result_divide = test_divide(x, y); std::cout << "Divide: " << result_divide << std::endl; } else { std::cout << "Invalid operation" << std::endl; return 1; } } return 0; }


