如何从汇编例程中调用 C 函数并使用 nasm 和 gcc 链接 C 和汇编文件

Posted

技术标签:

【中文标题】如何从汇编例程中调用 C 函数并使用 nasm 和 gcc 链接 C 和汇编文件【英文标题】:how to call C functions from assembly routines and link the C and assembly files using nasm and gcc 【发布时间】:2012-01-14 15:06:46 【问题描述】:

我想从程序集中调用至少 1 个 C 函数。这是因为我正在从头开始做我自己的微型操作系统(无中生有)。我想从我的引导加载程序调用 c 函数的原因。我可以理解汇编,但不擅长编写自己的程序。因此,如果我可以将控制从装配过程转移到 c 过程,我的工作就会变得更容易。

那么如何将汇编 pgm 和 C 程序文件合二为一。 即使文件大小超过 512 字节,我也可以。 我在 mingw 的帮助下在 Windows 7 上执行此操作。我的 c 编译器是 gcc,汇编器是 nasm

【问题讨论】:

检查this tutorial 并查看call kmain。您必须在汇编程序中实现正确的 C 调用约定。 【参考方案1】:

举个例子比较容易,我前段时间在互联网上找到了这个并将其保存为我的计算机上的源,但不知道从哪里来

; printf1.asm   print an integer from storage and from a register
; Assemble: nasm -f elf -l printf.lst  printf1.asm
; Link:     gcc -o printf1  printf1.o
; Run:      printf1
; Output:   a=5, eax=7

; Equivalent C code
; /* printf1.c  print an int and an expression */
; #include 
; int main()
; 
;   int a=5;
;   printf("a=%d, eax=%d\n", a, a+2);
;   return 0;
; 

; Declare some external functions
;
        extern  printf      ; the C function, to be called

        SECTION .data       ; Data section, initialized variables

        a:  dd  5       ; int a=5;
fmt:    db "a=%d, eax=%d", 10, 0 ; The printf format, "\n",'0'


        SECTION .text                   ; Code section.

        global main     ; the standard gcc entry point
main:           ; the program label for the entry point
    push    ebp     ; set up stack frame
    mov     ebp,esp
    mov eax, [a]    ; put a from store into register
    add eax, 2      ; a+2
    push    eax     ; value of a+2
    push    dword [a]   ; value of variable a
    push    dword fmt   ; address of ctrl string
    call    printf      ; Call C function
    add     esp, 12     ; pop stack 3 push times 4 bytes

    mov     esp, ebp    ; takedown stack frame
    pop     ebp     ; same as "leave" op

mov eax,0       ;  normal, no error, return value
ret         ; return

【讨论】:

csee.umbc.edu/portal/help/nasm/sample.shtml#printf1 在哪里找到。 我在尝试调用 puts 时收到 /usr/bin/ld: test2.o: relocation R_X86_64_PC32 against symbol 'puts@@GLIBC_2.2.5' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: final link failed: bad value collect2: error: ld returned 1 exit status 错误。 已解决。创建可执行文件时必须使用-no-pie。 @SouravKannanthaB:参见Can't call C standard library function on 64-bit Linux from assembly (yasm) code re:在 PIE 可执行文件中调用 libc 函数,GCC 在现代发行版中的默认设置。 (您评论的答案是 32 位代码,无论如何都不会在 64 位模式下汇编,但 extern foo / call foo 部分在两种模式下都是相同的。)

以上是关于如何从汇编例程中调用 C 函数并使用 nasm 和 gcc 链接 C 和汇编文件的主要内容,如果未能解决你的问题,请参考以下文章

如何让 VBA 子例程调用将数组传递给子例程中的另一个函数的函数

从汇编代码调用库中的 C 函数

从Assembly调用C函数(printf)时的Segfault

TableView:如何从 didSelectRowAtIndexPath 例程中选择另一行的值

如何从另一个汇编文件中调用汇编函数?

从 Fortran 调用 C 函数,其中 C 函数名称最初是从 C 传入的