C和汇编的双向调用以及一些问题

经过一步一步的写引导扇区,现在已经完成了,接下来的一步是写加载器。

加载器loader.bin是加载内核并且设置为保护模式,并且做一些描述符的初始化。但是接下来遇到的问题是如何使用C语言加速汇编的编写。

[提外话]这次用汇编的经历简直是尴尬,各种错误,但是一步一步还是克服了,一个一个的debug,了解了'利其器'的重要性。同时还知道了不要盲目迷失在‘器’中,关键还是一个思考的大脑。见另一篇,nasm汇编语法总结。

使用C语言和使用汇编其实只是使你的运算过程加快了,在数学逻辑的角度和内存的角度思考编码,而不是寄存器的角度(各种组合啥的),而且编译器可以提供动态的偏移计算,但是同时也会加大犯错的几率,所以一个好的程序员必须要一步一步的使用工具,不然很容易遗留一些不好的习惯,比如没想清楚接口就开始编码,最后发现接口错了,如果是汇编那么工作量相当大。而c语言修改方便,所以容易这个习惯被保留。

编译器的原理: C编译器就是将一些汇编中寄存器操作隐藏了,方便了核心的思考。

互相调用:平台ELF格式

原理:首先ELF格式的各个代码段和代码symbol其实就是汇编中的symbol名称。统一最后就是一个地址(address),但是在elf中这些标号信息会被保留。一些全局的标号比如说_start之类的需要引出被别人调用的就需要放到global中,这样可以保证在使用-strip的时候不会被删除。因为global的意思就是申明对外部可见,为了链接目的。由于最后function啥的都是symbol =>  address . 所以用c语言和汇编可以互相调用

C调用汇编函数ass_func:首先C函数需要申明extern res ass_func(**args**) 。也就是完整的申明,和调用其他的编译单元的C函数一样。其中的参数啥的是自己定义的接口,你自己定义的。调用则是和C调用一样。同时汇编代码必须有一个ass_func:标号'段'。同时在[section .text]中的global中申明global ass_func将这个symbol导出,这样链接时就不会出现问题。

汇编调用C函数c_func:    首先C函数要导出,但是对于一般函数来说是啥都不用做的,只要不用static就好。然后汇编使用extern c_func ;表明这个段是外面的段,不是内部申明的,其实这个是和link链接有关的。nasm只是使用这个符号作为输出.o文件的一个处理而已。然后使用call ass_func ;

调用约定(calling convention):使用cdecl或者其他的调用约定,很重要,因为不同的约定,你的汇编代码写法是不同的。只有遵守一样的规范才不会出错误。但是gcc的话目前的方法就是__attribute__((cdecl))。因为默认不是cdecl。同时还要制定gcc -m32 -c file.c。如果没用-m32会出现warning 而且会忽略制定的约定。当然这个m32表示的是代码是machine 32上的,也就是i80386上的。估计是x86-64位的机器上不支持?以后写64位系统在探究吧。

链接的平台:ld命令可以把多个.o文件链接。但是需要满足同一个平台的问题。因为链接完了就是在某个机器上执行的代码了,肯定和平台有关,估计要填写啥参数,做啥初始化处理啥的。所以编译决定了位数。而链接需要制定仿真器(如果平台不同)。

所以: nasm -f elf32 ;;;   gcc -m32 ;;;  需要配合ld -melf_i386才可以运行在64位的linux上。完结。

将来的问题:为啥必须要gcc -m32才可以使用cdecl调用约定。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值