Inline Assembly Language

CS 301: Assembly Language Programming Lecture, Dr. Lawlor

It's possible on most compilers to include a little bit of assembly code right inside your C or C++ file, called "inline assembly" because the assembly is inside the C/C++.  How you do this depends on what compiler you're using.

The downside of inline assembly is you're tied to a particular combination of hardware instruction set, and software interface to access it.  The upside is you can access the full feature set of the bare hardware, without needing to write the entire program in assembly.

Microsoft Inline Assembly:

Here's a simple example in Microsoft Visual C++ inline assembly:
int foo(void) {
int x=3;
__asm{
rol x,5 // bit rotate x by 5 bits
};
return x;
}
Note that:
A more complicated example:
int foo(void) {
int joe=1234, fred;
__asm{
mov eax,joe ; eax = joe;
add eax,2 ; eax += 2;
mov fred,eax ; fred = eax
};
return fred;
}
This is clearly very convenient!  But what happens if we try to do the same thing with a variable named "al"?  (Remember, "al" is a register on x86!)

Also, a given variable may be stored in a register, or in memory somewhere.  If we use an instruction that will only accept registers, but the variable is actually stored in memory, the code may not compile  ("invalid operand type").  The solution is to manually copy the variable into a register, like we did with eax above.

Defining Functions in Inline Assembly

You get much more control if you define the entire function in assembly language.  This is also the only decent way to make inline assembly work on Mac OS X or Linux with the gcc/g++ compiler (the default gnu inline assembly syntax is terrible.)

extern "C" long my_func(long x);

__asm__ (
".intel_syntax noprefix /* use good syntax */ \n\
.text /* make executable */  \n\
my_func:\n\
  mov rax,rdi\n\
  add rax,100\n\
  ret\n\
\n\
.att_syntax prefix\n"
);


long foo(void) {
	int x=5;
	return my_func(x);
}

(Try this in NetRun now!)

Notice that if we're defining the function: