先来看一个简单的Makefile,我们把它放在目录/boot下,可以用来编译boot.bin和loader.bin。

# Makefile for boot

# Programs, flags, etc.
ASM = nasm
ASMFLAGS = -I include/ # This Program
TARGET = boot.bin loader.bin # All Phony Targets
.PHONY : everything clean all # Default starting position
everything : $(TARGET) clean :
rm -f $(TARGET) all : clean everything boot.bin : boot.asm include/load.inc include/fat12hdr.inc
$(ASM) $(ASMFLAGS) -o $@ $< loader.bin : loader.asm include/load.inc include/fat12hdr.inc include/pm.inc
$(ASM) $(ASMFLAGS) -o $@ $<

以字符#开头的行是注释。=用来定义变量,这里的ASM和ASMFLAGS就是两个变量,要注意的是,使用它们的时候要用$(ASM)和$(ASMFLAGS),而不是它们的原型。

.PHONY暂时不管,来看一下Makefile的最重要的语法:

target : prerequisites
command

上面这样的形式代表两层意思:

1.要想得到target,需要执行命令command。

2.target依赖prerequisites,当prerequisites中至少有一个文件比target文件新时,command才被执行。

比如这个Makefile的最后两行,翻译出来就是:

1.要想得到loader.bin,需要执行“$(ASM) $(ASMFLAGS) -o $@ $<”。

2.loader.bin依赖于以下文件:

a.loader.asm

b.include/load.inc

c.include/pm.inc

d.include/fat12hdr.inc

当它们中至少有一个比loader.bin新时,command被执行。

$@代表target;$<代表prerequisites的第一个名字。联系前面我们说过的$(ASM)和$(ASMFLAGS),这个命令行便等价于:

nasm -o loader.bin loader.asm

在Makefile中我们容易注意到,不但boot.bin和loader.bin两个文件后面有冒号,everything、clean和all后面也有冒号,可是它们3个并不是3个文件,仅仅是动作名称而已。如果运行“make clean”,将会执行“rm -f $(TARGET)”,也即“rm -f boot.bin loader.bin”。

all后面跟着的是clean和everything,这表明如果执行“make all”,clean和everything所表示的动作将分别被执行。下面就是make all执行的结果:

>make all

rm -f boot.bin loader.bin

nasm -I include/ -o boot.bin boot.asm

nasm -I include/ -o loader.bin loader.asm

刚才的关键字.PHONY,其实是表示它后面的名字并不是文件,而仅仅是一种行为的标号。

未完。。。

编译方法:

make image

运行结果:

源码

操作系统开发系列—12.e.Makefile的更多相关文章

  1. 操作系统开发系列—12.f.在内核中添加中断处理 ●

    因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断. 要做的工作有两项:设置8259A和建立IDT. /*========= ...

  2. 操作系统开发系列—12.c.从Loader加载ELF内核,顺便解释下函数调用过程 ●

    实际上,我们要做的工作是根据内核的Program header table的信息进行类似下面这个C语言语句的内存复制: memcpy(p_vaddr, BaseOfLoaderPhyAddr+p_of ...

  3. 操作系统开发系列—12.g.在内核中设置键盘中断

    8259A虽然已经设置完成,但是我们还没有真正开始使用它呢. 所有的中断都会触发一个函数spurious_irq(),这个函数的定义如下: PUBLIC void spurious_irq(int i ...

  4. 操作系统开发系列—12.d.扩充内核 ●

    现在把esp.GDT等内容放进内核中,我们现在可以用C语言了,只要能用C,我们就避免用汇编. 下面看切换堆栈和GDT的关键代码: ; 导入函数 extern cstart ; 导入全局变量 exter ...

  5. 操作系统开发系列—12.b.从Loader跳入保护模式

    现在,内核已经被我们加载进内存了,该是跳入保护模式的时候了. 首先是GDT以及对应的选择子,我们只定义三个描述符,分别是一个0~4GB的可执行段.一个0~4GB的可读写段和一个指向显存开始地址的段: ...

  6. 操作系统开发系列—12.a.从Loader到内核 ●

    Loader要做两项工作,我们先来做第一项,把内核加载到内存: 1.加载内核到内存. 2.跳入保护模式. 首先编译无内核时: nasm boot.asm -o boot.bin nasm loader ...

  7. 操作系统开发系列—13.g.操作系统的系统调用 ●

    在我们的操作系统中,已经存在的3个进程是运行在ring1上的,它们已经不能任意地使用某些指令,不能访问某些权限更高的内存区域,但如果一项任务需要这些使用指令或者内存区域时,只能通过系统调用来实现,它是 ...

  8. 操作系统开发系列—11.ELF格式 ●

    ELF文件的结构如下图所示: ELF文件由4部分组成,分别是ELF头(ELF header).程序头表(Program header table).节(Sections)和节头表(Section he ...

  9. 操作系统开发系列—9.Loader

    一个操作系统从开机到开始运行,大致经历“引导—>加载内核入内存—>跳入保护模式—>开始执行内核”这样一个过程.也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列 ...

随机推荐

  1. Cordova webapp实战开发:(1)为什么选择 Cordova webapp?

    很长时间没有专注写代码了,即使写点代码也主要是写写敏捷个人app,这个App主体内容是我用了一周的时间,使用PhoneGap+JQueryMobile搭建的,之所以会比较快的完成,是因为11年我在做建 ...

  2. django多条件筛选搜索(项目实例)

    多条件搜索在很多网站上都有用到,比如京东,淘宝,51cto,等等好多购物教育网站上都有,当然网上也有很多开源的比楼主写的好的多了去了,仅供参考,哈哈 先来一张效果图吧,不然幻想不出来是什么样的,前端样 ...

  3. 127.0.0.1\SQLEXPRESS连接异常

    当你的数据库为SQLEXPRESS时,在程序的数据库连接字符串的服务Server使用127.0.0.1\SQLEXPRESS时,如下: 它会显示一异常: Server Error in '/' App ...

  4. LINQ使用Lambda表达式选择几列

    学习LINQ的Lambda的表达式,尝试从数据集合中,选择其中几列. 创建一个model: source code: namespace Insus.NET.Models { public class ...

  5. asp.net应用程序生命周期

    asp.net应用程序生命周期(流程文字描述版) 请求——>IIS——>ISAPI映射——>交给asp.net(即为IIS的扩展)——>通知Application类创建一个应用 ...

  6. javascript小数点后4舍5进

    toFixed();获得小数点后面多少为数字.四舍五入的方法. 例如: var floatNum = 5.234 var temp = floatNum.toFixed(1); -- temp = 5 ...

  7. TCP 与 UDP

    TCP Transmission Control Protocol,传输控制协议,传输层通信协议. 采用“带重传的肯定确认”(Positive Acknowledge with Retransmiss ...

  8. ASP.NET MVC 网站开发总结(五)——Ajax异步提交表单之检查验证码

    首先提出一个问题:在做网站开发的时候,用到了验证码来防止恶意提交表单,那么要如何实现当验证码错误时,只是刷新一下验证码,而其它填写的信息不改变? 先说一下为什么有这个需求:以提交注册信息页面为例,一般 ...

  9. 富客户端 wpf, Winform 多线程更新UI控件

    前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的 ...

  10. PHP替代正则匹配的高效函数

    strpos() - 查找字符串首次出现的位置 strrpos() 函数查找字符串在另一字符串中最后一次出现的位置(区分大小写). strripos() 函数查找字符串在另一字符串中最后一次出现的位置 ...