1

私は時計を作ろうとしているので、ASM と arduino を使っています。ほとんどの場合、プレーン C で問題ありませんが、BCD から 10 進数へのコンバーターに出力する時間を準備するために、ASM を使用することにしました。8086 C++/ASM で次のコードを書きましたが、私のコンピューターでは問題なく動作します。

#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
    for(int num = 0; num < 16; num++) {
        int bin[4];
        bin[0] = bin[1] = bin[2] = bin[3] = 0;
        asm("movl %%ebx, %%eax;"
            "andl $8, %%eax;"
            "cmp $0, %%eax;"
            "je a;"
            "movl $1, %0;"
            "jmp b;"
            "a: movl $0, %0;"
            "b: movl %%ebx, %%eax;"
            "andl $4, %%eax;"
            "cmp $0, %%eax;"
            "je c;"
            "movl $1, %1;"
            "jmp d;"
            "c: movl $0, %1;"
            "d: movl %%ebx, %%eax;"
            "andl $2, %%eax;"
            "cmp $0, %%eax;"
            "je e;"
            "movl $1, %2;"
            "jmp f;"
            "e: movl $0, %2;"
            "f: movl %%ebx, %%eax;"
            "andl $1, %%eax;"
            "cmp $0, %%eax;"
            "je g;"
            "movl $1, %3;"
            "jmp h;"
            "g: movl $0, %3;"
            "h: nop"
            : "=r" (bin[0]), "=r" (bin[1]), "=r" (bin[2]), "=b" (bin[3])
            : "b" (num)
            : "%eax"
            );
        cout << num << ": ";
        for(int i = 0; i < 4; i++) {
            cout << bin[i];
        }
        cout << endl;
    }
    return 0;
}

ただし、Arduinoで実行するように変更すると、完全に機能しなくなります。

  for(uint8_t num = 0; num < 16; num++) {
  uint8_t bin[4];
  bin[0] = bin[1] = bin[2] = bin[3] = 0;
  asm("mov __tmp_reg__, %[val];"
    "and __tmp_reg__, $8;"
    "cmp __tmp_reg__, $0;"
    "je a;"
    "mov %[bit8], $1;"
    "rjmp b;"
    "a: mov $0, %[bit8];"
    "b: mov %[val], __tmp_reg__;"
    "and __tmp_reg__, $4;"
    "cmp __tmp_reg__, $0;"
    "je c;"
    "mov %[bit4], $1;"
    "rjmp d;"
    "c: mov $0, %[bit4];"
    "d: mov %[val], __tmp_reg__;"
    "and __tmp_reg__, $2;"
    "cmp __tmp_reg__, $0;"
    "je e;"
    "mov %[bit2], $1;"
    "rjmp f;"
    "e: mov $0, %[bit2];"
    "f: mov %[val], __tmp_reg__;"
    "and __tmp_reg__, $1;"
    "cmp __tmp_reg__, $0;"
    "je g;"
    "mov %[bit1], $1;"
    "rjmp h;"
    "g: mov $0, %[bit1];"
    "h: nop"
    : [bit8] "=r" (bin[0]), [bit4] "=r" (bin[1]), [bit2] "=r" (bin[2]), [bit1] "=r" (bin[3])
    : [val] "r" (num)
    : "r0"
    );

8086 コードは、期待どおりの出力を提供します。

0: 0000
1: 0001
2: 0010
3: 0011
...
13: 1101
14: 1110
15: 1111

しかし、Arduino で実行されたコードは、別の出力を提供します。

0: 5000
1: 0000
2: 0000
3: 0000
... (ゼロが続く)
13: 0000
14: 0000
15: 0000

ご想像のとおり、5 を返すと、コードは役に立たなくなります。そして、ソースに 5 に近いものがない場合に 5 を返す方法についてはわかりません。私はここで何をすべきか途方に暮れているので、本当に助けが必要です.

ATMega32U プロセッサを搭載した Arduino Leonardo を使用しています。Arduinoソフトウェア(AVR-GCCでコンパイル)によって生成された実行可能ファイルを逆アセンブルしようとしましたが、入れたコードを見つける努力のどこにもたどり着けないようです.

お時間をいただきありがとうございます、Stack Overflow。

4

1 に答える 1

2

あなたが持っているコードは、次のように C++ で簡単に書くことができます:

 int bin[4] = {};

 bin[0] = !!(num & 8);
 bin[1] = !!(num & 4);
 bin[2] = !!(num & 2);
 bin[3] = !!(num & 1);

また:

int bin[4];
int bit = 8;
for(int i = 0; i < 4; i++)
{
    bin[i] = !!(num & bit);
    bit >>= 1;
}

気に入らない場合!!(これにより、「次の値を取得し、0 [false の場合] または 1 [true の場合] のいずれかになります)、次のように置き換えることができます。

for(int i = 0; i < 4; i++)
{
    bin[i] = (num >> 3 - i) & 1;
}

bin最高のインデックスの最高ビットの通常のケースではなく、意図的に最低のインデックスの最高ビットが必要だと思います。

于 2013-03-11T01:39:54.140 に答える