如何使用LLVM模块级内联汇编定义和调用函数?

时间:2018-09-23 03:54:59

标签: llvm llvm-ir

LLVM具有使我们能够将本机汇编指令直接放入.ll文件中的功能。

 module asm "inline asm code goes here"

https://llvm.org/docs/LangRef.html#module-level-inline-assembly

实际上,.s输出文件包含这些指令。

但是我该如何编写一个完整的函数并从同一个文件中的LLVM代码调用它呢?

有人可以提供一个简单的示例.ll,其中以LLVM代码编写的@main()调用到内联module asm中定义的函数中(理想情况下传递一个或两个参数)并退出的返回值?

我问是因为我想将this code从NASM移植到LLIR。它直接使用系统调用输出Hello World,而无需链接到标准库(因此,如果有一种方法可以进行系统调用而又无需进入本机程序集,那么我也想听听)。

1 个答案:

答案 0 :(得分:2)

我不确定llvm模块级别的内联汇编是否可与nasm一起使用。 希望下面列出的示例能够提供一些见识。基本上,我们想在llvm ir中声明该函数,该函数将在链接时解析。

; source_filename = file.ll

module asm ".format:"
module asm "    .string \22%d, hello world %s\n\22"
module asm "    .text"
module asm "    .globl print"
module asm "    .type print @function"
module asm "print:"
module asm "        pushq   %rbp"
module asm "        movq    %rsp, %rbp"
module asm "        subq    $16, %rsp"
module asm "        movl    %edi, -4(%rbp)"
module asm "        movq    %rsi, -16(%rbp)"
module asm "        movq    -16(%rbp), %rdx"
module asm "        movl    -4(%rbp), %eax"
module asm "        movl    %eax, %esi"
module asm "        leaq    .format(%rip), %rdi"
module asm "        movl    $0, %eax"
module asm "        call    printf@PLT"
module asm "        movq    %rbp, %rsp"
module asm "        popq    %rbp"
module asm "        ret"

@.str = global [16 x i8] c", how are you?\0A\00"

declare void @print(i64, i8*)

define i32 @main() {
start:
  %cast210 = getelementptr [16 x i8], [16 x i8]* @.str, i64 0, i64 0
  call void @print(i64 10, i8* %cast210)
  ret i32 0
}

编译并运行

llc file.ll -filetype=obj -o file.o
ld -o test ./file.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o -lc -melf_x86_64
./test