Reputation: 5585
I'm trying to multiply in assembler by shifting and adding and I get the weirdest output from the following code. If the last two function calls in the int main are commented out I get a normal result but otherwise I get a normal result for the first call and two garbage results for the second and third?
#include <iostream>
using namespace std;
int times_ten(int multiply_by_ten)
{
int multiplied_by_ten = 0;
//this multiplies by 10
__asm__("shld %%eax,%1;"
"movl %%eax,%%ebx;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"addl %%ebx,%%eax;"
: "=r" (multiplied_by_ten)
: "a" (multiply_by_ten)
);
return multiplied_by_ten;
}
int times_hundred(int multiply_by_hundred)
{
int multiplied_by_hundred = 0;
//this multiplies by 100
__asm__("shld %%eax,%1;"
"shld %%eax,%1;"
"movl %%eax,%%ebx;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"movl %%eax,%%edx;"
"shld %%eax,%1;"
"addl %%ebx,%%eax;"
"addl %%edx,%%eax;"
: "=r" (multiplied_by_hundred)
: "a" (multiply_by_hundred)
);
return multiplied_by_hundred;
}
int main()
{
cout<<times_hundred(1)<<endl;
cout<<times_ten(1)<<endl;
cout<<times_hundred(1)<<endl;
return 0;
}
The following has the clobber list but it wont compile. the errors are below it.
#include <iostream>
using namespace std;
int times_ten(int multiply_by_ten)
{
int multiplied_by_ten = 0;
//this multiplies by 10
__asm__("shld %%eax,%1;"
"movl %%eax,%%ebx;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"addl %%ebx,%%eax;"
: "=r" (multiplied_by_ten)
: "a" (multiply_by_ten)
: "%%eax", "%%ebx"
);
return multiplied_by_ten;
}
int times_hundred(int multiply_by_hundred)
{
int multiplied_by_hundred = 0;
//this multiplies by 100
__asm__("shld %%eax,%1;"
"shld %%eax,%1;"
"movl %%eax,%%ebx;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"shld %%eax,%1;"
"movl %%eax,%%edx;"
"shld %%eax,%1;"
"addl %%ebx,%%eax;"
"addl %%edx,%%eax;"
: "=r" (multiplied_by_hundred)
: "a" (multiply_by_hundred)
: "%%eax", "%%ebx", "%%edx"
);
return multiplied_by_hundred;
}
int main()
{
cout<<times_hundred(1)<<endl;
cout<<times_ten(1)<<endl;
cout<<times_hundred(1)<<endl;
return 0;
}
|In function 'int times_ten(int)':|
error: unknown register name '%%ebx' in 'asm'|
error: unknown register name '%%eax' in 'asm'|
In function 'int times_hundred(int)':|
error: unknown register name '%%edx' in 'asm'|
error: unknown register name '%%ebx' in 'asm'|
error: unknown register name '%%eax' in 'asm'|
In function 'int main()':|
error: unknown register name '%%edx' in 'asm'|
error: unknown register name '%%ebx' in 'asm'|
error: unknown register name '%%eax' in 'asm'|
error: unknown register name '%%ebx' in 'asm'|
error: unknown register name '%%eax' in 'asm'|
error: unknown register name '%%edx' in 'asm'|
error: unknown register name '%%ebx' in 'asm'|
error: unknown register name '%%eax' in 'asm'|
||=== Build finished: 13 errors, 0 warnings ===|
Upvotes: 1
Views: 2978
Reputation: 5585
This code works now.
#include <iostream>
using namespace std;
int times_ten(int multiply_by_ten)
{
int multiplied_by_ten = 0;
//this multiplies by 10
__asm__("shl $1, %%eax;"
"movl %%eax,%%ebx;"
"shl $2, %%eax;"
"addl %%ebx,%%eax;"
: "=a" (multiplied_by_ten)
: "0" (multiply_by_ten) : "%ebx"
);
return multiplied_by_ten;
}
int times_hundred(int multiply_by_hundred)
{
int multiplied_by_hundred = 0;
//this multiplies by 100
__asm__("shl $2, %%eax;"
"movl %%eax,%%ebx;"
"shl $3, %%eax;"
"movl %%eax,%%edx;"
"shl $1, %%eax;"
"addl %%ebx,%%eax;"
"addl %%edx,%%eax;"
: "=a" (multiplied_by_hundred)
: "0" (multiply_by_hundred) : "%ebx","%edx"
);
return multiplied_by_hundred;
}
int main()
{
cout<<times_hundred(1)<<endl;
cout<<times_ten(1)<<endl;
cout<<times_hundred(1)<<endl;
return 0;
}
Upvotes: 0
Reputation: 19965
After you've fixed the %% clobber problem, change the output register:
...
"addl %%edx,%%eax;"
: "=a" (multiplied_by_hundred)
: "a" (multiply_by_hundred)
: "%eax", "%ebx", "%edx"
from "=r" to "=a". Edit: This works with clang, but not gcc. Sorry.
Upvotes: 1