If you have ever wondered is there a way to instrument or insert some low level code into your high level language program, inline assembly is the answer. It is a simple way of inserting some assembly instruction/s into C plus plus program using a simple keyword asm.
The actual usage of the keyword is as asm(), but it is not a function. Hence the values passed in the parenthesis are not parameters. This keyword indicates whatever that is contained within the quotes in the parenthesis of asm should not be resolved at the compile time, instead should be as it is inserted in the code.
Usage: asm("assemly code to be inserted");
Example
int main()
{
asm("mov $0x01, %edx");
}
{
asm("mov $0x01, %edx");
}
Corresponding assembly:
If you try using asm like a function, where you store some instruction in to a string variable and then pass the string as a parameter to asm (remember asm is not a function), it will fail. Example:
string buffer="mov %edx, 0x01";
asm(buffer);
It will throw an error, because asm is not a function and is resolved at the compile time. It expects input as asm("input"). In such cases asm will be unable to resolve value contained in buffer.
If you try asm("buffer"), it will compile but throw error as expected.
When you try to explicitly instrument the assembly code in to your C or C++ program, you cannot directly instrument the assembly code as you see in the object dump of your code. You have o follow certain norms to make it compatible to your code. These rules are specified below.
When you try to explicitly instrument the assembly code in to your C or C++ program, you cannot directly instrument the assembly code as you see in the object dump of your code. You have o follow certain norms to make it compatible to your code. These rules are specified below.
Rules:
1. When you place the assembly instruction in quotes all the registers will be followed by a percentage (%) sign.
Example: eax will be written as %eax.
2. Values or constants will be followed by dollar sign ($).
Example: 0x1 will become $0x1
3. Memory addresses can be written as it is.
4. For instructions that include word, dword and qword, you should append your opcode (for example mov) with l, w or q respectively and remove the whole word.
Example: mov will become movq.
5. If assembly uses relative addressing like [rbp-0x18] it should be replaced with -0x18(%rbp).
Sample code:
4. For instructions that include word, dword and qword, you should append your opcode (for example mov) with l, w or q respectively and remove the whole word.
Example: mov will become movq.
5. If assembly uses relative addressing like [rbp-0x18] it should be replaced with -0x18(%rbp).
Sample code:
After you compile it:
This is how the assembly of main will look like.
Command to obtain it: objdump -d inline
You can seethe inserted code in <main>: mov $0x1,%edx