第13部分-Linux x86 64位汇编 独立函数文件
将各个函数字自包含在自己的文件中,并且连接在一起成为最终产品。
函数的文件不需要使用_start段。不过需要将函数名字声明为全局标签,以便其他程序能够访问,使用.globl命令来完成。
例如:
.section .text
.type area,&function
.globl area
area:
示例
函数文件:
文件为area.s
.section .text
.type area, @function;//定义函数area
.globl area
area:
push %rbp;//压栈ebp寄存器
mov %rsp, %rbp;//将esp赋值为ebp
subq $8, %rsp;//设置rsp网上走,这里其实没有实际作用,64位系统中一个压栈就是8个字节
fldpi;//加载π到st0
filds 16(%rbp) ;//加载ebp+8就是调用函数前压栈的参数到st0,π移到st1
fmul %st(0), %st(0) ;//st0和st0相乘,保存在st0
fmulp %st(0), %st(1) ;//st0和st1相乘,结果在栈顶st0
fstps -8(%rbp) ;//保存结果到栈中, 8个字节,也就是挡墙rsp所指的位置。
movl -8(%rbp), %eax;//最后将结果移动到eax寄存器,是单精度值
mov %rbp, %rsp;//恢复esp寄存器
pop %rbp;//恢复ebp寄存器
ret;//返回函数
-
-
- 主程序文件
-
主程序不包含area函数的任何代码。
文件为funcmain.s
.extern printf ;//调用外部的printf函数
.section .data
precision:
.byte 0x7f, 0x00
resultstr:
.ascii "Area result is %f.\n"
.section .bss
.lcomm bresult, 4
.section .text
.globl _start
_start:
nop
finit;//FPU初始化
fldcw precision;//加载FPU控制器
push $10;//加载10到栈中
call area;//调用area函数
addq $8, %rsp;//增加8个字节,即跳过压栈的参数
movl %eax, bresult;//保存结果到result
movq bresult,%xmm0;//结果复制到xmm0寄存器
cvtps2pd %xmm0,%xmm0;//转化单精度为双精度
movq $resultstr,%rdi
call printf
push $2
call area
addq $8, %rsp
movl %eax, bresult
movq $resultstr,%rdi
movq bresult,%xmm0
cvtps2pd %xmm0,%xmm0
call printf
push $120
call area
addq $8, %rsp
movl %eax, bresult
movq $resultstr,%rdi
movq bresult,%xmm0
cvtps2pd %xmm0,%xmm0
call printf
mov $60,%rax
syscall
进行编译连接:
as -g -o area.o area.s
as -g -o funcmain.o funcmain.s
ld -o funcmain funcmain.o area.o -lc -I /lib64/ld-linux-x86-64.so.2