- Say you want to call some assembly from C. Your choices are to:
- Write a new ".S" or ".asm" file, assemble it with your favorite assembler, and link it in to your existing code.
- Use the hideous gcc or nice Microsoft inline assembler syntax to embed the assembly inside a subroutine.
- Write a self-contained assembly subroutine using the gcc inline assembly syntax.
I'd like you to try the third option here.
Here's
a working example x86 gcc C++ program that calls an assembly subroutine
"mul_them" that takes two arguments. Right now, "mul_them" just
returns the first argument. Change "mul_them" to multiply the two
arguments and return the product.
Executable NetRun Example
x86 Cheat Sheet
extern "C" int mul_them(int a,int b); /* C++ prototype for assembly routine */
__asm__( /* assembly code, inserted as a string */
"mul_them:\n"
" mov 4(%esp),%eax # Pull first argument (a) off the stack\n"
" mov 8(%esp),%ebx # Pull second argument (b) off the stack\n"
" # YOUR ASSEMBLY CODE HERE \n"
" ret # Returns value stored in %eax\n"
);
int foo(void) {
return mul_them(read_input(),0x20000);
}
Once
your program is working correctly, given input 2 foo should exit with
0x40000. Don't worry about overflow, unless you want to show off!
- Start with problem 1, but now add a stack frame: save and restore %ebp. You must access the parameters relative to %ebp, not %esp! Your program should give the same output as in problem 1.
- Start with problem 1, but now write "mul_them" in PowerPC assembly (see cheat sheet). Again, don't worry about overflow.
Executable NetRun Example
extern "C" int mul_them(int a,int b); /* C++ prototype for assembly routine */
__asm__( /* PowerPC assembly code, inserted as a string */
".section \".text\"\n"
"mul_them:\n"
" # YOUR CODE HERE\n"
" blr # Returns value stored in %r3\n"
);
int foo(void) {
return mul_them(read_input(),0x20000);
}
- In addition to calling assembly from C/C++, it's sometimes useful
to call C/C++ from assembly. Call the subroutine "bar(3,7)" using
x86 assembly code where indicated below. Be sure to clean up the
arguments off the stack when done!
NetRun Link
extern "C" void bar(int a,int b) /* C++ routine callable from Assembly */
{
std::cout<<a<<" "<<b<<"\n";
fflush(stdout);
}
int foo(void) {
__asm__( /* assembly code, inserted as a string */
" # YOUR CODE HERE\n"
);
return 0;
}
Like HW3 & HW4, you'll turn these problem in by just naming them HW5_1, HW5_2, etc. in