Search code examples
cassemblyfasm

embed assembly produced code into C program using FASM


I am trying to link assembly-compiled with c-compiled code, and I get undefined reference error during linking phase. This is how i do it:

[niko@dev1 test]$ cat ssefuncs.asm 
format ELF64 
EQUAL_ANY       = 0000b
RANGES          = 0100b
EQUAL_EACH      = 1000b
EQUAL_ORDERED       = 1100b
NEGATIVE_POLARITY = 010000b
BYTE_MASK    = 1000000b


asm_sse:
    movntdqa xmm0,[eax]
    pcmpestri xmm0,[ecx],0x0

    ret
[niko@dev1 test]$ fasm ssefuncs.asm ssefuncs.o
flat assembler  version 1.71.50  (16384 kilobytes memory)
1 passes, 405 bytes.
[niko@dev1 test]$ ls -l ssefuncs.o
-rw-r--r-- 1 niko niko 405 Jan 31 14:52 ssefuncs.o
[niko@dev1 test]$ objdump -M intel -d ssefuncs.o

ssefuncs.o:     file format elf64-x86-64


Disassembly of section .flat:

0000000000000000 <.flat>:
   0:   67 66 0f 38 2a 00       movntdqa xmm0,XMMWORD PTR [eax]
   6:   67 66 0f 3a 61 01 00    pcmpestri xmm0,XMMWORD PTR [ecx],0x0
   d:   c3                      ret    
[niko@dev1 test]$ cat stest.c 
void asm_sse();

int main() {

    asm_sse();
}
[niko@dev1 test]$ gcc -c stest.c 
[niko@dev1 test]$ gcc -o stest ssefuncs.o stest.o
stest.o: In function `main':
stest.c:(.text+0xa): undefined reference to `asm_sse'
collect2: error: ld returned 1 exit status
[niko@dev1 test]$ 

Looking at the ELF file, it is very thin and I don't see any symbols. :

[niko@dev1 test]$ readelf -a ssefuncs.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          149 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         4
  Section header string table index: 3

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .flat             PROGBITS         0000000000000000  00000040
       000000000000000e  0000000000000000 WAX       0     0     8
  [ 2] .symtab           SYMTAB           0000000000000000  0000004e
       0000000000000030  0000000000000018           3     2     8
  [ 3] .strtab           STRTAB           0000000000000000  0000007e
       0000000000000017  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.symtab' contains 2 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .flat

No version information found in this file.
[niko@dev1 test]$ 

What is the correct way to embed FASM produced assembly code into a C program?


Solution

  • Subroutine names in assembly code are usually simply labels for certain positions within the instruction stream. They are not automatically made visible for linking with external object code. To make it possible, a symbol should be declared public. Also, by convention the code in ELF files resides in the .text section. Your assembly file should look like this:

    format ELF64 
    EQUAL_ANY       = 0000b
    RANGES          = 0100b
    EQUAL_EACH      = 1000b
    EQUAL_ORDERED       = 1100b
    NEGATIVE_POLARITY = 010000b
    BYTE_MASK    = 1000000b
    
    section '.text' code readable executable
    
    asm_sse:
        movntdqa xmm0,[eax]
        pcmpestri xmm0,[ecx],0x0
    
        ret
    
    public asm_sse