CS 301 - Homework 5

(HW_4 Reloaded)

  1. Say you want to call some assembly from C.  Your choices are to:

  2. 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.
     
    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"
    " mul %ebx # Multiplies eax by ebx \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!

  3. 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.
    extern "C" int mul_them(int a,int b); /* C++ prototype for assembly routine */

    __asm__( /* assembly code, inserted as a string */
    "mul_them:\n"
    " push %ebp\n"
    " mov %esp,%ebp\n"
    " mov 8(%ebp),%eax # Pull first argument (a) off the stack\n"
    " mov 12(%ebp),%ebx # Pull second argument (b) off the stack\n"
    " mul %ebx # Multiplies eax by ebx \n"
    " leave # same as mov %ebp, %esp & pop %ebp\n"
    " ret # Returns value stored in %eax\n"
    );

    int foo(void) {
    return mul_them(read_input(),0x20000);
    }
  4. Start with problem 1, but now write "mul_them" in PowerPC assembly (see cheat sheet).  Again, don't worry about overflow.  
    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"
    " mullw %r3, %r3, %r4\n"
    " blr # Returns value stored in %r3\n"
    );

    int foo(void) {
    return mul_them(read_input(),0x20000);
    }
  5. 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!
    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 */
    " push $7\n"
    " push $3\n"
    " call bar\n"
    " add $8,%esp # Clean up stack afterwards, by popping both arguments\n"
    );
    return 0;
    }


Like HW3 & HW4, you'll turn these problem in by just naming them HW5_1, HW5_2, etc. in NetRun.  These should be run in the "Whole Subroutine (file)" mode of NetRun, not the "Subroutine Fragment" mode as we've been running before.  Your code MUST preserve all the registers code is supposed to preserve, and your code must not crash after running!

Problems are due Monday, October 17, at Midnight. 

O. Lawlor, ffosl@uaf.edu
Up to: Class Site, CS, UAF