使用FASM将程序集生成的代码嵌入到C程序中

时间:2016-01-31 21:05:14

标签: c assembly fasm

我正在尝试将汇编编译与c编译代码链接,并且在链接阶段我得到未定义的引用错误。我就是这样做的:

[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]$ 

查看ELF文件,它非常薄,我看不到任何符号。 :

[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]$ 

将FASM生成的汇编代码嵌入C程序的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

汇编代码中的子程序名称通常只是指令流中某些位置的标签。对于与外部对象代码的链接,它们不会自动显示。为了使其成为可能,应该声明符号public。此外,按照惯例,ELF文件中的代码位于.text部分。您的程序集文件应如下所示:

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

答案 1 :(得分:-1)

这在很大程度上取决于所使用的编译器。例如。 GCC(以及克隆,clang)有一个非常广泛的工具,用于在线编写汇编语言片段,处理与周围代码连接的例行细节(根据需要保存已修饰的寄存器,将输入放在它们的位置)可以使用和获取结果,并将输入/输出与给定的匹配。这通常是最简单的方法。

如果以上不是一个选项,您应该首先编写一个简短的C程序,然后将其编译为程序集。像$itemArray = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q"); $arrLength = count($itemArray); for($i = 0; $i < $arrLength; ++$i){ if($i % 3 == 0){ if($i != 0){ ?> </div> <?php } ?> <div class="swiper-slide big"> <div class="item"><?php echo $itemArray[$i]; ?></div> </div> <div class="swiper-slide normal"> <?php }else{ ?> <div class="item"><?php echo $itemArray[$i]; ?></div> <?php } } 这样的东西会给你一个带汇编语言的cc -g -S somefile.csomefile.s(或其他调试启用)应该在代码中包含注释,允许更容易的反向引用C.这将允许您对编译器的结果进行反向工程,并通过弄乱来作为独立程序集文件的起点编译函数的内容。

正如@LaurentH的评论所说,通常编译生成的汇编语言中的源符号名称,以防止与外部符号冲突,例如,预先-g或甚至某些字符在特定程序集中合法但不在C中,例如_.