【发布时间】:2020-06-06 16:42:50
【问题描述】:
我想从我的 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
我可以将它作为程序执行,它会输出“Hello, world!” 但是当我试图从这样的 C 代码中调用 print 时:
#include <stdio.h>
extern int print();
int main(){
int g;
g = print();
printf("Hello from c!, %d\n", g);
}
编译使用:
$gcc -c main.c test
它只打印“Hello from c, 13”,这意味着该函数被调用并返回了一些字符,但不打印任何东西!
我做错了什么?
附: 当我尝试像这样编译 prog 时:
$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
【问题讨论】:
-
总体上做得很好,但我怀疑 sys_write() 或 write() 实际上使用 printf() 样式格式或查看附加参数。通常在汇编语言级别上,必须在多个写入的部分中构造格式化输出,或者将格式化文本构建到数据区域中,然后一次性写出完整的格式化缓冲区。 tutorialspoint.com/assembly_programming/…
-
这是否有助于您解决 -fPIE 问题? stackoverflow.com/questions/46123505/…
-
用
gcc -no-pie -c test.s -o test.o和gcc -no-pie -o main main.c test.o编译似乎可以解决问题... -
这是 32 位代码。使用
gcc -m32 main.c test.s -o main构建它。您可以选择使用-fno-pie -no-pie,因为这对于 32 位效率来说是个好主意。