使用 FASM 将汇编生成的代码嵌入到 C 程序中
embed assembly produced code into C program using FASM
我正在尝试 link 使用 C 编译代码进行汇编编译,但在 linking 阶段出现未定义引用错误。我是这样做的:
[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 程序中的正确方法是什么?
这在很大程度上取决于所使用的编译器。例如。 GCC(以及通过克隆,clang)有一个非常广泛的工具,用于编写内联汇编语言片段,处理与周围代码接口的例行细节(根据需要保存损坏的寄存器,放置输入可以使用它们的地方并获取结果,并将 inputs/outputs 与给定的内容匹配)。这通常是最简单的方法。
如果上述方法不是一个选项,您应该先编写一个简短的 C 程序,然后将其编译为汇编。 cc -g -S somefile.c
之类的东西应该会给你一个 somefile.s
汇编语言。 -g
(或其他调试支持)应该在代码中包含注释,允许更容易地向后引用 C。这将允许您对编译器的结果进行逆向工程,并作为独立程序集文件的起点,通过弄乱编译函数的内部结构。
正如@LaurentH 的评论所说,编译器通常会破坏生成的汇编语言中源符号的名称,以防止与外部符号发生冲突,例如前置 _
或什至某些字符在特定程序集中合法但在 C 中不合法,例如 .
或 $
.
汇编代码中的子程序名称通常只是指令流中某些位置的简单标签。与外部目标代码链接时,它们不会自动可见。为使其成为可能,应声明一个符号 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
我正在尝试 link 使用 C 编译代码进行汇编编译,但在 linking 阶段出现未定义引用错误。我是这样做的:
[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 程序中的正确方法是什么?
这在很大程度上取决于所使用的编译器。例如。 GCC(以及通过克隆,clang)有一个非常广泛的工具,用于编写内联汇编语言片段,处理与周围代码接口的例行细节(根据需要保存损坏的寄存器,放置输入可以使用它们的地方并获取结果,并将 inputs/outputs 与给定的内容匹配)。这通常是最简单的方法。
如果上述方法不是一个选项,您应该先编写一个简短的 C 程序,然后将其编译为汇编。 cc -g -S somefile.c
之类的东西应该会给你一个 somefile.s
汇编语言。 -g
(或其他调试支持)应该在代码中包含注释,允许更容易地向后引用 C。这将允许您对编译器的结果进行逆向工程,并作为独立程序集文件的起点,通过弄乱编译函数的内部结构。
正如@LaurentH 的评论所说,编译器通常会破坏生成的汇编语言中源符号的名称,以防止与外部符号发生冲突,例如前置 _
或什至某些字符在特定程序集中合法但在 C 中不合法,例如 .
或 $
.
汇编代码中的子程序名称通常只是指令流中某些位置的简单标签。与外部目标代码链接时,它们不会自动可见。为使其成为可能,应声明一个符号 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