Search code examples
cgcccodeblocks

How to compile DB and DD assembly instructions using GCC compiler


I am trying to compile a legacy module(written in C) in my project using gcc compiler. I am using codeblocks IDE for compilation. I was able to resolve most of the issues i faced but not able to compile the below inline assembly code using gcc.

extern void *RegisterTable;

    void REGISTER(void) {
      asm db 0,0,0
      asm dd word ptr RegisterTable
    }

gcc not able to identify db and dd instructions. Hence I tried to change the above code as shown below in the hope of compiling in gcc

    extern void *RegisterTable;
    void REGISTER(void) {
      asm
      (
      ".byte 0,0,0\n\t"
      ".long word ptr RegisterTable\n\t"
      );
}

But this code also giving below error in the second line "".long word ptr RegisterTable\n\t"" as it is not able to recognize the PTR

Error: junk at end of line, first unrecognized character is `p'

Any help on how to compile this assembly code using gcc is greatly appreciated.

EDIT: The assembler used is 'as' which comes by default with gcc. Also this piece of code is to put the address of 'RegisterTable' function in a particular location - to be specific the first 'db' instruction puts the three zeros as the first 3 bytes of the code segment and the second 'dd' instruction puts the address of the RegisterTable function as the 4th bit of the code section - of the binary file.The binary file is in PE format(windows file format). And the downstream process which process the binary file looks for this address for its processing. It is done by reading the PE header structure first and then finding the code section from the PE header and after finding the start of code section the downstream process uses the below code to read the address of the RegisterTable function which was put by the above code in my question

  // Get Registration table 
  fseek(f, Section.ptrToRaw+3, SEEK_SET); //Skip the 0,0,0
  fread(&ptrTab, sizeof(ptrTab), 1, f);
  M->RTab = GetRegisterTable32(M->Mem, ptrTab-PEHdr.imgBase-PEHdr.baseOfData);

Solution

  • gcc allows you to use inline asm outside of functions. So you can simply do the following, outside of any function:

    asm(".text \n\t"
        ".byte 0,0,0 \n\t"
        ".long RegisterTable");
    

    This will place, within your code section, three zero bytes followed by the address of RegisterTable.

    Note that the GNU assembler does not need anything analogous to word ptr; that is specific to MASM-like assemblers that want to keep track of object types.

    If your platform uses leading underscores on C-defined symbols, then you may have to use _RegisterTable instead.

    If the symbol REGISTER is used anywhere (not in the code you showed), then:

    asm(".global REGISTER \n\t"
        ".text \n\t"
        "REGISTER: \n\t"
        ".byte 0,0,0 \n\t"
        ".long RegisterTable");
    

    The hard part, however, is going to be to ensure that those three bytes are first in your executable's code segment. Just putting it at the top of your .c file probably won't work reliably. There is a good chance that the compiler and/or linker will place something else ahead of it, such as startup or library code. You may be able to accomplish this with a linker script but it may be painful. This is something I think you should ask as a separate question.

    In the long run, your best bet may be to figure out why the program needs to be parsing data out of its own executable files, as that's a weird thing to do, and redesign that aspect to use something that's easier and less fragile (e.g. read it from a separate flat file, or load a DLL).