やまものブログ

メモ書きブログです (^_^;A

ARM アセンブラ 簡単命令でソート処理

アセンブラのプログラミング経験が皆無なので、とにかく簡単なプログラムを組んでみました。4つの整数についてソート、合計、平均、範囲を求めるプログラムです。

#include <stdio.h>

int main(int argc, char *argv[])
{
        register int v0;
        register int v1;
        register int v2;
        register int v3;
        register int sum;
        register int avg;
        register int rng;
        register int tmp;

    v0 = atoi(argv[1]); v1 = atoi(argv[2]);
    v2 = atoi(argv[3]); v3 = atoi(argv[4]);
    printf("%d\t%d\t%d\t%d\n", v0, v1, v2, v3);

    // Sort
     asm volatile(" \
     srt00:    CMP   %0, %1; \
        BLE   srt01; \
        MOV   %4, %0; \
        MOV   %0, %1; \
        MOV   %1, %4; \
     srt01:    CMP   %1, %2; \
        BLE   srt02; \
        MOV   %4, %1; \
        MOV   %1, %2; \
        MOV   %2, %4; \
     srt02:    CMP   %2, %3; \
        BLE   srt10; \
        MOV   %4, %2; \
        MOV   %2, %3; \
        MOV   %3, %4; \
     srt10:    CMP   %0, %1; \
        BLE   srt11; \
        MOV   %4, %0; \
        MOV   %0, %1; \
        MOV   %1, %4; \
     srt11:    CMP   %1, %2; \
        BLE   srt20; \
        MOV   %4, %1; \
        MOV   %1, %2; \
        MOV   %2, %4; \
     srt20:    CMP   %0, %1; \
        BLE   srt30; \
        MOV   %4, %0; \
        MOV   %0, %1; \
        MOV   %1, %4; \
     srt30:    NOP; \
        " : "=r"(v0), "=r"(v1), "=r"(v2), "=r"(v3), "=r"(sum));
    // Sum
    asm volatile(" \
        ADD %4, %0, %1; \
        ADD %4, %4, %2; \
        ADD %4, %4, %3; \
        " : "=r"(v0), "=r"(v1), "=r"(v2), "=r"(v3), "=r"(sum));

    // Average
    asm volatile(" \
        MOV   %6, #0; \
        AND   %7, %4, #3; \
        CMP   %7, #1; \
        MOVGT %6, #1; \
        MOV   %5, %4, ASR #2; \
        ADD   %5, %5, %6; \
        " : "=r"(v0), "=r"(v1), "=r"(v2), "=r"(v3),
            "=r"(sum), "=r"(avg), "=r"(rng), "=r"(tmp));

    // Range
    asm volatile(" \
        SUB %6, %3, %0; \
        " : "=r"(v0), "=r"(v1), "=r"(v2), "=r"(v3),
            "=r"(sum), "=r"(avg), "=r"(rng), "=r"(tmp));

    printf("%d\t%d\t%d\t%d\n", v0, v1, v2, v3);
    printf("sum\t= %d\naverage\t= %d\nrange\t= %d\n", sum, avg, rng);
    //printf("tmp\t= %d\n", tmp);
    return 0;
}


本当はサブルーチンとか使ってエレガントに書きたかったのですが、それだけで試験当日になりそうだったので、べたに書いてみました。とりあえず、期待通りの動作を確認できて一安心です。

root@zynq:~# ./a.out 5 1 2 7
5    1    2    7
1    2    5    7
sum    = 15
average    = 4
range    = 6
root@zynq:~# ./a.out 5 1 2 6
5    1    2    6
1    2    5    6
sum    = 14
average    = 4
range    = 5
root@zynq:~# ./a.out 5 1 2 5
5    1    2    5
1    2    5    5
sum    = 13
average    = 3
range    = 4
root@zynq:~# ./a.out 5 1 2 -15
5    1    2    -15
-15    1    2    5
sum    = -7
average    = -2
range    = 20


インラインで register  変数をたくさん使うのは限界がありますね