在linux中从C代码调用汇编函数

在linux中从C代码调用汇编函数,c,linux,assembly,C,Linux,Assembly,我想从我的C程序调用一个打印函数。 汇编程序: #test.s .text .global _start .global print .type print, @function _start: call print # and exit. movl $0,%ebx # first argument: exit code. movl $1,%eax #

我想从我的C程序调用一个打印函数。
汇编程序:

 #test.s
.text

    .global _start
    .global print
    .type print, @function

_start:

        call print

        # and exit.

        movl    $0,%ebx         # first argument: exit code.
        movl    $1,%eax         # system call number (sys_exit).
        int     $0x80           # call kernel.

print:
    # write our string to stdout.

        movl    $len,%edx       # third argument: message length.
        movl    $msg,%ecx       # second argument: pointer to message to write.
        movl    $1,%ebx         # first argument: file handle (stdout).
        movl    $4,%eax         # system call number (sys_write).
        int     $0x80           # call kernel.

        mov $0,   %eax
        ret
.data

msg:
        .ascii  "Hello, world!\n"      # the string to print.
        len = . - msg                  # length of the string.
我可以使用以下工具进行组装和链接:

$as test.s -o test.o
$ld test.o -o test
我可以把它作为一个程序来执行,它会输出“你好,世界!” 但是当我试图从C代码调用print时,如下所示:

#include <stdio.h>
extern int print();

int main(){
    int g;
    g = print();
    printf("Hello from c!, %d\n", g);

}
$as test.s -o test.o
$gcc -c main.c -o main.o
$gcc main.c test.o 
它只打印“Hello from c,13”,这意味着调用了该函数并返回了大量字符,但不打印任何内容

我做错了什么

附言。 当我试图像这样编译prog时:

#include <stdio.h>
extern int print();

int main(){
    int g;
    g = print();
    printf("Hello from c!, %d\n", g);

}
$as test.s -o test.o
$gcc -c main.c -o main.o
$gcc main.c test.o 
我有一个错误:

/usr/bin/ld: test.o: in function `_start':
(.text+0x0): multiple definition of `_start'; /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: test.o: relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
好的,完成了!谢谢

我可以编译所有的应用程序

$as test.s -o test.o
$gcc -c main.c -o main.o
$gcc -no-pie main.c test.o 

一切都会好起来的

总的来说,这项工作做得很好,但我怀疑sys_write()或write()是否实际使用printf()样式的格式或查看其他参数。通常在汇编语言级别,必须在多个写操作的部分中构造格式化输出,或者将格式化文本构建到数据区域中,然后一次性写出完整的格式化缓冲区。这是否有助于您解决-fPIE问题?使用
gcc-no-pie-c test.s-o test.o
gcc-no-pie-o main.c test.o
编译似乎可以达到目的……这是32位代码。使用gcc-m32 main.c test.s-o main构建它。您可以选择使用
-fno pie-no pie
,因为这是一个提高32位效率的好主意。