概述
第72部分- Linux x86 64位汇编调用汇编库
如果希望汇编语言函数和C以及C++程序一起工作,必须显式的遵守C样式的函数格式。
汇编语言函数的源代码文件包含在编译器命令行中。
例如:
gcc -o exe xx.c xx.s xx2.s xx3.s
创建汇编语言函数的目标文件时,不必使用ld命令连接代码,因为本身可能缺少_start标签。使用as进行汇编即可。
一起编译C文件和汇编文件
汇编文件asmfunc.s如下:
.section .data
testdata:
.ascii "This is a test message from the asm functionn"
datasize:
.int 45
.section .text
.type asmfunc, @function
.globl asmfunc
asmfunc:
movl $1, %rax;//write系统调用
movl $1, %rdi;//stdout
movl $testdata, %rsi;//字符串
movl datasize, %rdx;//字符串长度
syscall;//系统调用
ret
C文件mainprog.c如下:
#include <stdio.h>
int main()
{
printf("This is a test.n");
asmfunc();
printf("Now for the second time.n");
asmfunc();
printf("This completes the test.n");
return 0;
}
进行编译连接如下:
# gcc -o mainprog mainprog.c asmfunc.s -no-pie
产生一个完整的可执行程序文件。
这里使用了参数-no-pie,因为不用会报错:
`.data' can not be used when making a PIE object;
tips:默认编译器是PIE(position independent executable)对象的,在支持它的目标上生成与位置无关的可执行文件, 生成一个可以在任意基地址处加载的可执行文件,而不是其加载地址在ld时间固定的“普通”可执行文件。PIE通常被认为是一种强化机制(允许地址随机化来影响主程序中代码和数据的地址),但它也可以具有其他用途,例如使二进制文件更适合于无MMU的系统。
这里-no-pie表示非PIE对象。
PIC和PIE
位置无关的代码(PIC)和位置无关的可执行文件(PIE)并不是什么新鲜事物,但是编译开关,可以忽略,直到我们不能使用为止。
位置无关代码(PIC)是很老的东西。 早在我们拥有MMU和分页之前,所有进程都必须共享物理地址空间,可以确保可以在任何地址加载程序。 当CPU演进并且每个进程可以将其自己的逻辑地址空间任意映射到任何物理地址时,PIC不再是必需的。
早期被教导要在构建.so文件时放置-fPIC的原因是为了确保多个进程可以使用同一代码,这些进程会将同一物理内存映射到各种虚拟地址。 实际上,它消除了所有绝对寻址,而用相对寻址或可以为每个进程分叉的小型跳转表代替它。
在2000年代初之前,PIC仅限于共享库。 可执行文件仍使用绝对寻址,不是PIC时可以依赖PIC,反之则不然。 随着地址空间布局随机化(ASLR)的出现,也使可执行文件与位置无关也变得有意义,这样攻击者就无法预测其内存映射,从而使缓冲区溢出漏洞更加复杂.
现在的操作系统将检查可执行文件是否与位置无关(PIE),如果启用,则启用ASLR。 默认情况下,编译器可能会或可能不会强制执行此操作,具体取决于您的系统。
实际上,位置独立共享库是从使用-fPIC构建的对象创建的,而位置独立可执行文件是从通过-fPIE构建的对象创建的。
这里需要注意的是如下几点:
- 可以从PIC或PIE对象(.o)和PIC或PIE静态库(.a)创建位置独立PIE的可执行文件
- 只能从PIC对象或静态库创建PIC共享库
- 可以从任何对象或静态库中创建非PIE可执行文件1
Linux下编译共享库时,必须加上-fPIC参数,否则在链接时会有错误提示。
如果-fPIE和-shared同时使用,生成的结果即可作为动态库,也可作为可执行程序。作为动态库时,必须满足:不存在main函数且模块中不存在对外输出的全局变量。这是因为-fPIE默认总是将生成的位置无关代码看作是属于程序本身。
PIC是在生成动态链接库时使用(Linux中的so),PIE是在生成可执行文件时使用。
反汇编
使用反汇编查看二进制文件
objdump -D mainprog
可以看到有一个段是main,这个段包含来实现C程序代码在系统上生成的汇编语言代码。
00000000004004e7 <main>:
4004e7: 55 push %rbp
4004e8: 48 89 e5 mov %rsp,%rbp
4004eb: 48 8d 3d e2 00 00 00 lea 0xe2(%rip),%rdi # 4005d4 <_IO_stdin_used+0x4>
4004f2: e8 f9 fe ff ff callq 4003f0 <puts@plt>
4004f7: b8 00 00 00 00 mov $0x0,%eax
4004fc: e8 29 00 00 00 callq 40052a <asmfunc>
400501: 48 8d 3d dc 00 00 00 lea 0xdc(%rip),%rdi # 4005e4 <_IO_stdin_used+0x14>
400508: e8 e3 fe ff ff callq 4003f0 <puts@plt>
40050d: b8 00 00 00 00 mov $0x0,%eax
400512: e8 13 00 00 00 callq 40052a <asmfunc>
400517: 48 8d 3d df 00 00 00 lea 0xdf(%rip),%rdi # 4005fd <_IO_stdin_used+0x2d>
40051e: e8 cd fe ff ff callq 4003f0 <puts@plt>
400523: b8 00 00 00 00 mov $0x0,%eax
400528: 5d pop %rbp
400529: c3 retq
000000000040052a <asmfunc>:
40052a: 48 c7 c0 01 00 00 00 mov $0x1,%rax
400531: 48 c7 c7 01 00 00 00 mov $0x1,%rdi
400538: 48 c7 c6 30 10 60 00 mov $0x601030,%rsi
40053f: 48 8b 14 25 5d 10 60 mov 0x60105d,%rdx
400546: 00
第一列是程序内存空间中的内存位置。第二列显示汇编语言代码生产的指令代码。
可以看到另一个段就是asmfunc。我们编译的时候是合在一起了。
最后
以上就是忧郁羽毛为你收集整理的第72部分- Linux x86 64位汇编调用汇编库第72部分- Linux x86 64位汇编调用汇编库的全部内容,希望文章能够帮你解决第72部分- Linux x86 64位汇编调用汇编库第72部分- Linux x86 64位汇编调用汇编库所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复