自制操作系统日记(5):跳转到C语言执行

简介: 在上篇中切换了CPU的64位模式,但后面是失败的,并没有真正切换,也没有相关的验证代码,本篇中终于修正并执行了C代码

代码仓库地址:https://github.com/freedom-xiao007/operating-system

简介

在上篇中切换了CPU的64位模式,但后面是失败的,并没有真正切换,也没有相关的验证代码,本篇中终于修正并执行了C代码

CPU模式切换修正

上篇中后面发现系统在Get SVGA时卡住了,并没有向下执行

后面搜索资料,最终尝试下来,感觉上使用qeme好像有些问题,同样的镜像在qemu中会不断循环重启,而在bochs中不会,所以我们重新抄了下代码,并且换了下虚拟机,换成bochs

文章的参考链接如下,写的很好,又学到了很多

我们直接抄它的三个文件:bootsect.asm、setup.asm、head.asm

在head.asm中,他是直接在里面模拟的c的main函数,我们将其注释掉,并修改call main为我们的c的start函数,具体修改如下:

修改call main 为 call _start; 在104行左右

注释掉所有的main函数代码,115到120行左右

push 0 ;These are the parameters to main :-)
push 0 ;这些是调用main程序的参数(指init/main.c)。
push 0  
push L6 ;return address for main, if it decides to.
push _start ;'_main'是编译程序对main的内部表示方法。
jmp  setup_paging   ;这里用的JMP而不是call,就是为了在setup_paging结束后的
                    ;ret指令能去执行C程序的main() 
L6:
jmp L6 ;main程序绝对不应该返回到这里。不过为了以防万一,
     ;所以添加了该语句。这样我们就知道发生什么问题了。
     
     
     


; _main:      ;这里暂时模拟出C程序main() 
;      mov  esi,mainmsg                ;保护模式DS=0,数据用绝对地址访问
;      mov  cl, 0x09                   ;蓝色
;      mov  edi, 0xb8000+22*160        ;指定显示在某行,显卡内存地址需用绝对地址
;      call printnew                   ;0xb8000为字符模式下显卡映射到的内存地址 
;      ret  

这样对他的相关改造就OK了

C代码植入

关于运行C代码的部分我们还是跟随《30天自制操作系统》的思路:将C代码转换成汇编码,和head.asm拼接到一起,然后直接编译即可

根据大体思路,我们的具体操作如下:

  • 1.编写C代码
  • 2.使用GCC将C代码生成.O文件
  • 3.使用objconv将.O文件转成nasm汇编文件
  • 4.使用python脚本处理调转换得到的汇编文件的一些不需要的地方
  • 5.编写运行脚本,拼接文件,编译,运行

具体细节如下:

1.C代码编写

我们就简单起名叫start.c吧,里面就打印一个字符串,无限循环

typedef unsigned char uint8_t;

void put_str(uint8_t* message);

void start(void) {
    put_str("0123456789");
    while(1);
}

put_str的函数目前我们用汇编进行实现,新增func.asm文件,编写put_str函数

_put_str:
    mov  esi, esp ;保护模式DS=0,数据用绝对地址访问
    mov  cl, 0x09                   ;蓝色
    mov  edi, 0xb8000+22*160        ;指定显示在某行,显卡内存地址需用绝对地址
    call printnew                   ;0xb8000为字符模式下显卡映射到的内存地址 
    ret  

打印字符串就参考的head.asm里面的main函数

2.使用GCC将C代码生成.O文件

在Windows10上使用GCC需要安装一些东西

首先安装命令choco,管理员方式打开powershell,输入下面的命令:

set-executionpolicy remotesigned
iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex

然后使用命令安装MinGW

choco install mingw

安装完成后,重启启动下powershell就可以使用gcc命令,如下就是使用gcc将.c文件生成.o文件

gcc -m32 -fno-asynchronous-unwind-tables -s -O2 -c -o .\\c\\start.o .\\c\\start.c

我们目前还是使用32位吧(命令的-m32),64位有点把控不住......

3.使用objconv将.O文件转成nasm汇编文件

这个工具需要进行下载,下载地址为:https://www.agner.org/optimize/#objconv,在页面上找Object file converter,然后点击下载后对应安装即可

将.o文件转换成nasm文件命令如下:

D:\\software\\objconv\\objconv.exe -fnasm .\\c\\start.o .\\c\\nasm\\start.asm

4.使用python脚本处理调转换得到的汇编文件的一些不需要的地方

生成的文件中有很多地方错误和不必要的代码,需要进行处理

如何人工去处理太慢了,这里使用编写python脚本进行处理

脚本大致如下,还是比较简单的,就是读文件,读取一行内容后进行过滤,如果符合条件,写入新文件中

if __name__ == "__main__":
    with open("E:\\code\\other\\self\\operating-system\\c\\clean\\start.asm", "w") as fw:
        with open("E:\\code\\other\\self\\operating-system\\c\\nasm\\start.asm", "r") as fr:
            content = fr.readline()
            while content:
                if content.startswith("global") or content.startswith("extern"):
                    content = fr.readline()
                    continue
                content = content.replace("noexecute", "")
                content = content.replace("execute", "")
                fw.write(content)
                content = fr.readline()

在搜索的资料中,需要进行下面的操作:

  • 使用global定义的函数名称标签(extern目前暂时去掉)
  • 去掉.SECTION一行中的execute或noexecute,和(如果有需要的话)align=N语句
  • 去掉default rel行(目前的文件中没有发现,暂时没有处理)

这样就大致处理完成了

5.编写运行脚本,拼接文件,编译,运行

下面就是最后的拼接和编译运行了,我们将所有的步骤放到bat脚本中,一键运行,脚本内容如下:

# 编译
D:\\software\\NASM\\nasm.exe bootsect.asm -o bootsect.bin -l bootsect.lst
D:\\software\\NASM\\nasm.exe setup.asm -o setup.bin  -l setup.lst

# 将C代码转换后拼接编译
gcc -m32 -fno-asynchronous-unwind-tables -s -O2 -c -o .\\c\\start.o .\\c\\start.c
D:\\software\\objconv\\objconv.exe -fnasm .\\c\\start.o .\\c\\nasm\\start.asm
D:\\software\\python3\\python.exe E:\\code\\python\\self\\tools\\tools\\objconv2nasm_clearn.py
copy /B head.asm+.\\c\\clean\\start.asm+func.asm  kernel.asm
D:\\software\\NASM\\nasm.exe kernel.asm -o kernel.bin -l kernel.lst

# 将所有的文件整合成镜像
copy /B bootsect.bin+setup.bin+kernel.bin  os.iso

# 使用bochs运行镜像
D:\\software\\Bochs-2.7\\bochs -q -f D:\\software\\Bochs-2.7\\dlxlinux\\bochsrc_m.bxrc

bochs的安装和使用说明参考后面的,运行结果如下:

image.png

bochs安装使用说明

首先bochs的下载地址为:https://sourceforge.net/projects/bochs/

解压后,我们需要修改:D:\software\Bochs-2.7\dlxlinux\bochsr.bxrc成D:\software\Bochs-2.7\dlxlinux\bochsr_m.bxrc

主要修改文件的对应路径和启动方式,整个配置文件如下:

###############################################################
# bochsrc.txt file for DLX Linux disk image.
###############################################################

# how much memory the emulated machine will have
megs: 32

# filename of ROM images,替换原来的相对路径为绝对路径
romimage: file=D:\\software\\Bochs-2.7\\BIOS-bochs-latest
vgaromimage: file=D:\\software\\Bochs-2.7\\VGABIOS-lgpl-latest

# what disk images will be used 
# 指明启动的镜像为我们的os.iso镜像文件
floppya: 1_44=E:\\code\\other\\self\\operating-system\\os.iso, status=inserted
floppyb: 1_44=floppyb.img, status=inserted

# hard disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="D:\\software\\Bochs-2.7\\dlxlinux\\hd10meg.img", cylinders=306, heads=4, spt=17

# choose the boot disk.修改启动方式为软盘
boot: floppy

# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx

#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga

# where do we send log messages?
log: bochsout.txt

# disable the mouse, since DLX is text only
mouse: enabled=0

# set up IPS value and clock sync
cpu: ips=15000000
clock: sync=both

# enable key mapping, using US layout as default.
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so 
# in the DLX Linux example I'm enabling keyboard_mapping so that paste 
# will work.  Cut&Paste is currently implemented on win32 and X windows only.

# 替换原来的相对路径为绝对路径
keyboard: keymap=D:\\software\\Bochs-2.7\\keymaps/x11-pc-us.map
#keyboard: keymap=D:\\software\\Bochs-2.7\\keymaps/x11-pc-fr.map
#keyboard: keymap=D:\\software\\Bochs-2.7\\keymaps/x11-pc-de.map
#keyboard: keymap=D:\\software\\Bochs-2.7\\keymaps/x11-pc-es.map

这样就OK了,这个是启动的配置文件

在我们的一键运行脚本中,配置使用该文件即可

D:\\software\\Bochs-2.7\\bochs -q -f D:\\software\\Bochs-2.7\\dlxlinux\\bochsrc_m.bxrc

总结

最后的打印字符串还是有点问题,但最终的目的是达到了,调用C语言的代码(后面也查了资料,但目前的水平短时间内解决不了,只能放到后面看看了)

参考链接

相关文章
|
4月前
|
NoSQL Linux Redis
redis源码调试---vscode使用技巧-----C语言跳转到函数定义
redis源码调试---vscode使用技巧-----C语言跳转到函数定义
72 0
|
2月前
|
Unix Linux C语言
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
20 0
|
7月前
|
Shell Linux Go
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
69 0
|
12月前
|
API C语言 开发者
|
Unix Linux 开发工具
【看表情包学Linux】了解操作系统 | 目录内容的显示 | 目录跳转 | 基本创建与删除操作(二)
本章将浅谈一下 "操作系统是什么" 的问题,随后通过讲解一些 Linux 下的基本指令,显示目录内容、跳转操作和文件的创建与删除。在讲解的同时我会穿插一些知识点,比如 Linux 隐藏文件、路径等基础知识。
129 0
【看表情包学Linux】了解操作系统 | 目录内容的显示 | 目录跳转 | 基本创建与删除操作(二)
|
人工智能 Linux C++
【看表情包学Linux】了解操作系统 | 目录内容的显示 | 目录跳转 | 基本创建与删除操作(一)
本章将浅谈一下 "操作系统是什么" 的问题,随后通过讲解一些 Linux 下的基本指令,显示目录内容、跳转操作和文件的创建与删除。在讲解的同时我会穿插一些知识点,比如 Linux 隐藏文件、路径等基础知识。
227 0
【看表情包学Linux】了解操作系统 | 目录内容的显示 | 目录跳转 | 基本创建与删除操作(一)
|
编译器 C语言
【C 语言】二级指针作为输入 ( 二维数组 | 二维数组内存大小计算 | 指针跳转步长问题 )
【C 语言】二级指针作为输入 ( 二维数组 | 二维数组内存大小计算 | 指针跳转步长问题 )
140 0
【C 语言】二级指针作为输入 ( 二维数组 | 二维数组内存大小计算 | 指针跳转步长问题 )
|
22天前
|
监控 Unix Linux
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
32 0
|
23天前
|
Linux 编译器 开发者
Linux设备树解析:桥接硬件与操作系统的关键架构
在探索Linux的庞大和复杂世界时🌌,我们经常会遇到许多关键概念和工具🛠️,它们使得Linux成为了一个强大和灵活的操作系统💪。其中,"设备树"(Device Tree)是一个不可或缺的部分🌲,尤其是在嵌入式系统🖥️和多平台硬件支持方面🔌。让我们深入了解Linux设备树是什么,它的起源,以及为什么Linux需要它🌳。
Linux设备树解析:桥接硬件与操作系统的关键架构
|
2月前
|
Linux 数据安全/隐私保护 虚拟化
Linux技术基础(1)——操作系统的安装
本文是龙蜥操作系统(Anolis OS) 8.4 的安装指南,用户可以从[龙蜥社区下载页面](https://openanolis.cn/download)获取ISO镜像。安装方法包括物理机的光驱和USB闪存方式,以及虚拟机中的VMware Workstation Pro设置。安装过程涉及选择语言、配置安装目标、选择软件集合和内核,设置Root密码及创建新用户。安装完成后,可通过文本模式或图形化界面验证系统版本,如Anolis OS 8.4,标志着安装成功。