手机写操作系统之 制作第1个启动盘
2.手机写操作系统之
制作第1个启动盘
建立目录
一般手机上没有文件工具,需要下载一个文件管理。
在手机里使用文件管理建立目录
A/ya/
再建立子目录
code
out
final
termux对手机目录的访问加上/sdcard,比如:
cd /sdcard/A/ya
启动程序boot
看看有名的boot程序
电脑开始启动后,首先在磁盘0号磁道0号扇区处寻找boot程序,这个程序只有512字节大小,如果是以0x55,0xAA两个字节结尾,电脑将认为这是一个boot程序,然后电脑将这个程序读入内存地址0x7c00:0000处开始执行。
一个最简单的boot.asm
使用文本编辑器:
[BITS 16]
[ORG 0x7c00]
jmp main
ns db 'hello world!'
main:
mov ax, cs
mov ds, ax
mov es, ax
mov cx,12 ;循环12次
mov bx,0 ;从数组[0]开始
mov ah,0eh
next:
mov al,[ns+bx]
int 10h
inc bx
dec cx
jnz next ;cx不为0则继续
po:
jmp po
times 510-($-$$) db 0
db 0x55
db 0xAA
将它保存到手机里的A/ya/code目录下
我们分析一下这个程序
$表示本指令地址 $$表示程序开始地址
times 510-($-$$) db 0 就是填入510-(本指令地址-程序开始地址)这么多个0
我们给它中间加点语句,让它在屏幕上显示Hello World
这里我们生成可执行文件格式
打开termux,输入命令
cd /sdcard/A/ya
nasm code/boot.asm -o out/boot.bin
把boot.bin写入启动盘,用Hex editor将512 b大小的boot.bin复制到A盘镜像文件中,这样做麻烦。为此使用两个软件工具:
create_img.cpp 创建启动盘
write_in_img.cpp 向启动盘写入数据
create_img.cpp
include
include <stdio.h>
include
include<stdlib.h>
//argv[1]=目标文件 创立镜像文件, 内容全为0,大小1474560
using namespace std;
int main (int argc,char* argv[])
{
int i;
for (i = 1; i <= argc; i++)
{
printf("argv[%d]=%s\n",i,argv[i]);
}
FILE *tof;
tof = fopen( argv[1],"r"); //只读方式打开一个binary目标文件
if( tof ==NULL) // 第一次需创建目标文件
{
printf("\nerror on open file,will creat new file\n");
tof = fopen (argv[1],"wb");
fseek(tof, 1474559, SEEK_SET); //相当于写入那么多0
putc(0, tof); // 写第1474560字节,1.44M软盘大小
}
printf("done\n");
fclose(tof); //关文件禁止读写才能对文件删除及改名
return 0;
}
write_in_img.cpp
include
include <stdio.h>
include
include <stdlib.h>
//argv[1]=目标文件 argv[2]=源文件 argv[3]=写入偏移量十进制 用法: ./write_in_img.o a.img setup.bin 0
using namespace std;
long get_file_size( FILE *fp )
{
if ( fp == NULL) return -1;
fseek(fp, 0L, SEEK_END );
return ftell( fp );
}
int main (int argc,char* argv[])
{
int i;
int ch;
int k = atoi(argv[3]); // 转换得到写入偏移量
FILE *fromf, *tof, *temp;
fromf = fopen( argv[2], "r" ); //只读方式打开源文件
tof = fopen( argv[1],"r"); //只读方式打开目标文件
if( tof ==NULL) // 第一次需创建目标文件
{
printf("\nerror on open file,use create_img.o to creat img file\n");
exit( 0 );
}
temp = fopen("t.img", "w+" ); //创建一个用于读写的空文件,中间文件,大小为0
fseek(tof, 0L, SEEK_SET ); //从新定位到文件开头
for (int i =0; i < k; i++) // 保留目标文件第一部分
{
ch = getc( tof );
putc(ch, temp);
}
long ja = get_file_size( fromf );
fseek(fromf, 0L, SEEK_SET ); //定位到源文件开头
for (int i =0; i < ja; i++) // 复制文件第二部分
{
ch = getc( fromf );
putc(ch, temp);
}
fseek ( tof, ja+k, SEEK_SET ); //指针指向从文件头开始ja+K个字节
ch = getc( tof );
i = 0;
while ( ch != EOF ) // 复制最后的第三部分
{
putc(ch, temp); // 写入文件
ch = getc( tof );
i++;
}
fclose(tof); //关文件禁止读写才能对文件删除及改名
fclose(fromf);
fclose(temp);
remove(argv[1]);
rename("t.img",argv[1]);
return 0;
}
下面我们将在虚拟机上模拟boot文件从软盘上启动的效果。
准备工作:
修改g.sh文件:
!/bin/sh
echo "=启动 ya=="
cd /sdcard/A/ya/
make
cd ~
cp -f /sdcard/A/ya/out ./
cd out
chmod 755 ./*
执行命令,当前目录下生成a.img文件
./create_img.o a.img
执行命令,向a.img写入代码,内容是boot.bin
写入磁盘位置从0偏移量起始,占1个扇区512字节
./write_in_img.o a.img boot.bin 0
结果复制到手机
cp -f ./a.img /sdcard/A/ya/final
cd ~
rm -r out
将g.sh存于手机目录A/ya
修改makefile文件:
######################
声明要编译的所有组成,这里的ya是本工程名称,可以取任何名字,这里就用ya
######################
ya:out/boot.bin out/create_img.o out/write_in_img.o
开始对各部分编译
out/boot.bin:code/boot.asm
nasm code/boot.asm -o out/boot.bin
制作内核映象工具
out/create_img.o:code/create_img.cpp
clang++ code/create_img.cpp -o out/create_img.o
写入文件,argv[1]=目标文件 argv[2]=源文件 argv[3]=写入偏移量
out/write_in_img.o:code/write_in_img.cpp
clang++ code/write_in_img.cpp -o out/write_in_img.o
######################
存为makefile,放在手机A/ya目录下
以上工作准备好了,开始使用sh + makefile制作启动盘
方法:
打开termux
cp -f /sdcard/A/ya/g.sh ./
运行
sh g.sh
查看手机目录A/ya/final,有a.img,用磁盘编辑工具查看a.img内容,为1474560字节,而且已经把boot.bin内容复制到a.img。
打开Limbo,开始设置,Machine 下拉菜单选new 填写名称ya点create 在弹出的菜单点击最下的Custom User Interface,Display 选VNC。Removable 勾选Floppy A --> open --> 手机目录下的A/ya/final/a.img
点击三角形Run --> 打开 RVNC,填写127.0.0.1:1 及名称,点OK,显示:
Booting from Floppy...
Hello world!
浙公网安备 33010602011771号