Assembler Stuff: Asm and Inline Asm
Posted 01-25-2012 at 07:15 PM by rainbowsally
Tags asm, assembler, computer mad science
Assembler Stuff: Asm and Inline Asm
Features:
Let's get right to the point...
Also, here's the gcc equivalent for the stdcall call types if you want it. Normally, in C, the caller cleans up the stack, though. Tends to be
faster.
Pick the one you're most familiar with; __stdcall, _stdcall, or stdcall
You only need those for the prototype declarations. Asm is asm.
To see the intel syntax disassembly (dest, src) type:
or remove the "-M ..." part for ATT (src, dest) disassembly.
Try the compile with adding the flag '--omit-frame-pointer' and look at the c_writevar code compared to test_writevar in objdump.
[If you don't have 'tofile', you can pipe it through 'more' or whatever...]
Here's what I get...
:-)
Features:
- Asm and inline asm examples
- Using C macros to create global function names
- Intel and ATT syntax
- Viewing disassembly in a *.s file and using objdump
Let's get right to the point...
Code:
// main.c // COMPILE: gcc main.c -o main --save-temps // take a look at the C asm output file, 'main.s' afterwar // 64 bit asm keeps part of the stack in registers in C, so let's // keep this simple and compilt it for 32 bit intel x86. #include <stdio.h> // We can use C macros to hide ugly details such as giving // the function a global name we can use to call it. We'll // use backslashes to span lines to make it more readable. #define LABEL(name) \ ".text;\n" \ ".globl "#name";\n" \ ".type " #name", @function;\n" \ ""#name":" #define FUNCTION(name) \ asm( \ ".text;\n" \ ".align 4\n" \ LABEL(name) \ ); // returns char* as a long long test_readvar(char* s); // sets [addr] = s void test_writevar(char** addr, const char* s); // functionally identical to this void c_writevar(char** addr, char* s) { *addr = s; } char* watch; // copy a value here to see it in a debugger // Let's create a stretch of throwaway code in C in which we // can compile some straight assembler routines. This basically // switches the assembler to compile in the .text section. void code_section() { // We are now in a code block created by C, i.e., the .text // section, so the following FUNCTION will be somewhat redundant // but certainly easier to read than the gory details of the full // declaration. // C pushes the params on the stack, right to left. This is // straight asm code so there is no frame pointer, esp points // to the return address, esp+4 points to first param in param // list. FUNCTION(test_readvar) // return contents of value on the stack asm( // This is the first opcode that executes in the call. "mov 4(%esp), %eax;" // Note that we don't need newlines after the semicolons // here, but if you have a syntax error there will be // few usable clues about where it occurred. // And this is the last byte to execute in this code. "ret;" ); // end function // Now let's try intel syntax FUNCTION(test_writevar) // (var, val) asm( ".intel_syntax noprefix;\n" // C let's us play with eax and edx, but others need to be // saved and restored. "MOV EAX, DWORD PTR [ESP+4];\n" // var "MOV EDX, DWORD PTR [ESP+8];\n" // val "MOV DWORD PTR [EAX], EDX;\n" // [var] = val "RET;\n" // if we don't switch back, C will choke on intel syntax ".att_syntax\n" ); } void thats_all_folks() {printf("That's All Folks!\n\n");} int main() { char*x = "testing"; // first test long addr = test_readvar(x); printf("readvar -> Addr: 0x%X\tValue: %s\n", addr, x); // second test, and also rerun first routine for printout test_writevar(&x, "finished"); addr = test_readvar(x); // to get new value printf("readvar -> Addr: 0x%X\tValue: %s\n", addr, x); // and we can inline asm with C as well asm( "call thats_all_folks;"); return 0; }
faster.
Pick the one you're most familiar with; __stdcall, _stdcall, or stdcall
Code:
#define __stdcall __attribute__((__stdcall__)) #define _stdcall __attribute__((__stdcall__)) #define stdcall __attribute__((__stdcall__))
To see the intel syntax disassembly (dest, src) type:
Code:
objdump -d main -M intel_syntax
Try the compile with adding the flag '--omit-frame-pointer' and look at the c_writevar code compared to test_writevar in objdump.
Code:
tofile objdump -d -M intel_syntax main
Here's what I get...
Code:
08048454 <c_writevar>: 8048454: 8b 44 24 04 mov eax,DWORD PTR [esp+0x4] 8048458: 8b 54 24 08 mov edx,DWORD PTR [esp+0x8] 804845c: 89 10 mov DWORD PTR [eax],edx 804845e: c3 ret 08048468 <test_writevar>: 8048468: 8b 44 24 04 mov eax,DWORD PTR [esp+0x4] 804846c: 8b 54 24 08 mov edx,DWORD PTR [esp+0x8] 8048470: 89 10 mov DWORD PTR [eax],edx 8048472: c3 ret
Total Comments 0