I'm trying to build a clock, so I'm working with ASM and an arduino. For most parts, plain C will be fine, but for preparing the time to be output to BCD to Decimal converters I decided to go with ASM. I wrote the following code in 8086 C++/ASM and it runs fine on my computer:
#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;
}
However, when I modified it to run on the Arduino, things stop working entirely:
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"
);
The 8086 code gives the output you'd expect:
0: 0000
1: 0001
2: 0010
3: 0011
...
13: 1101
14: 1110
15: 1111
But the code run on the Arduino gives a different output:
0: 5000
1: 0000
2: 0000
3: 0000
... (zeros continue)
13: 0000
14: 0000
15: 0000
As you can imagine, the code becomes useless if it returns... five. And I'm clueless as to how it could return 5 when nothing is anywhere close to 5 in the source. I'm at a loss as to what to do here, so I could really use some help.
I'm using the Arduino Leonardo, which has an ATMega32U processor. I've tried disassembling the executable generated by the Arduino software (which compiles it with AVR-GCC), but I can't seem to get anywhere in my efforts to find the code I put in.
Thanks for your time, Stack Overflow.
The code you have can EASILY be written in C++, like this:
int bin[4] = {};
bin[0] = !!(num & 8);
bin[1] = !!(num & 4);
bin[2] = !!(num & 2);
bin[3] = !!(num & 1);
or:
int bin[4];
int bit = 8;
for(int i = 0; i < 4; i++)
{
bin[i] = !!(num & bit);
bit >>= 1;
}
If you don't like !!
(which makes "take the next value and make it either 0 [if it's false] or 1 [if it's true]), you could replace it with:
for(int i = 0; i < 4; i++)
{
bin[i] = (num >> 3 - i) & 1;
}
I take it you intentionally want the highest bit in the lowest bin
index, rather than the usual case of highest bit in the highest index.