实现自己的打印函数

news2024/11/19 22:54:21

文章目录

  • 前言
  • 前置知识
  • 代码说明
  • 实验操作
    • 单字符打印
    • 字符串打印
    • 整形字符串打印

前言

本博客记录《操作系统真象还原》第六章实验的操作~

实验环境:ubuntu18.04+VMware , Bochs下载安装

实验内容

  1. 实现 put_char 单字符打印输出函数。
  2. 实现 put_str 字符串打印输出函数。
  3. 实现 put_int 整形字符串打印输出函数 。

前置知识

由于本章实验我们需要将C语言和汇编语言进行结合一起使用编程,因此需要给汇编语言进行使用调用约定。C语言遵循的调用约定是cdecl,和cdelc类似的stdcall。(感兴趣的读者可以简单了解)

汇编语言和 C 语言混合编程可分为2大类

  1. 单独的汇编代码文件与单独的 C 语言文件分别编译成目标文件后,一起链接成可执行程序(掌握)见原书 P260
  2. 内联汇编:在 C 语言中嵌入汇编代码,直接编译生成可执行程序。

代码说明

单字符打印

/lib/kernel/print.S

  1. 步骤
(1)备份寄存器现场。
(2)获取光标坐标值,光标坐标值是下一个可打印字符的位置。
(3)获取待打印的字符。
(4)判断字符是否为控制字符,若是回车符、换行符、退格符三种控制字符之一,则进入相应的处理
流程。否则,其余字符都被粗暴地认为是可见字符,进入输出流程处理。
(5)判断是否需要滚屏。
(6)更新光标坐标值,使其指向下一个打印字符的位置。
(7)恢复寄存器现场,退出。
  1. 原理
    put_char 的打印原理是直接写显存。

/lib/kernel/print.h

#ifndef __LIB_KERNEL_PRINT_H
#define __LIB_KERNEL_PRINT_H
#include "stdint.h"
void put_char(uint8_t char_asci);
#endif
  1. 条件编译指令#ifndef和#endif的作用:为防止头文件被重复包含,避免头文件中的变量等出现重复定义的情况。
  2. #include "stdint.h":这是让编译器到系统头文件所在的目录中找所包含的文件,这个目录通常是/usr/include。
  3. void put_char(uint8_t char_asci);:简单的声明,给出 put_char 函数(汇编语言编写)的原型。

/kernel/main.c

可以引入头文件编写程序

#include "print.h"
int main() {
    put_char('k');
    while(1);
}

实验操作

单字符打印

首先,为了更好的管理文件,在 lib 目录下可以建立 user 和 kernel 两个子目录。其中 lib/kernel/下存放供内核使用的库文件,lib/user/ 中是用户进程使用的库文件。

首先,在 lib/kernel 中创建 print.S 和 print.h文件。

(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo vim print.S
(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo vim print.h

编译print.S

(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ ls
print.h  print.S
(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo nasm -f elf -o  print.o print.S
(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ ls
print.h  print.o  print.S

编译main.c

sudo gcc -m32 -I lib/kernel/ -c -o kernel/main.o kernel/main.c
(base) user@ubuntu:/home/cooiboi/bochs$ sudo gcc -m32 -I lib/kernel/ -c -o kernel/main.o kernel/main.c

出现Bug:

In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h:9:0,
                 from lib/kernel/print.h:3,
                 from kernel/main.c:1:
/usr/include/stdint.h:26:36: fatal error: bits/libc-header-start.h: No such file or directory
 #include <bits/libc-header-start.h>
                                    ^
compilation terminated.

解决方法

sudo apt-get install gcc-multilib

】:需要增加-m32指令。否则,ld: i386:x86-64 architecture of input file `kernel/main.o’ is incompatible with i386 output

链接 main.o 和 print.o

一行写不下的写法:

sudo ld -m elf_i386  -Ttext 0xc0001500 -e main -o kernel/kernel.bin\
> kernel/main.o lib/kernel/print.o

或者下面这种

全部写在一行的写法:

sudo ld -m elf_i386  -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o

Bug

注1】出现下方的提示就是mian.o编译存在问题,需要重新编译一波!

(base) user@ubuntu:/home/cooiboi/bochs$ sudo ld -m elf_i386  -Ttext 0xc0001500 -e main -o kernel/kernel.bin > kernel/main.o lib/kernel/print.o
ld: warning: cannot find entry symbol main; defaulting to 00000000c000150

注2】:需要添加-m elf_i386命令。ld: i386 architecture of input file `lib/kernel/print.o’ is incompatible with i386:x86-64 output

写入虚拟内存

sudo dd if=/home/cooiboi/bochs/kernel/kernel.bin of=/home/cooiboi/bochs/boot/hd60M.img bs=512 count=200 seek=9 conv=notrunc
(base) user@ubuntu:/home/cooiboi/bochs$ sudo dd if=/home/cooiboi/bochs/kernel/kernel.bin of=/home/cooiboi/bochs/boot/hd60M.img bs=512 count=200 seek=9 conv=notrunc
4+1 records in
4+1 records out
2352 bytes (2.4 kB, 2.3 KiB) copied, 0.000127066 s, 18.5 MB/s

启动Bochs

sudo bin/bochs -f boot/bochsrc.disk
(base) user@ubuntu:/home/cooiboi/bochs$ sudo bin/bochs -f boot/bochsrc.disk

在这里插入图片描述
在这里插入图片描述

字符串打印

首先,修改print.S 和 print.h文件

(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo vim  print.S
(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo vim  print.h

编译print.S

sudo nasm -f elf -o  print.o print.S
(base) user@ubuntu:/home/cooiboi/bochs/lib/kernel$ sudo nasm -f elf -o  print.o print.S

修改main.c文件同时对其进行编译

(base) user@ubuntu:/home/cooiboi/bochs/kernel$ sudo vim main.c

在这里插入图片描述

sudo gcc -m32 -I lib/kernel/ -c -o kernel/main.o kernel/main.c
(base) user@ubuntu:/home/cooiboi/bochs$ sudo gcc -m32 -I lib/kernel/ -c -o kernel/main.o kernel/main.c

链接 main.o 和 print.o

sudo ld -m elf_i386  -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o
(base) user@ubuntu:/home/cooiboi/bochs$ sudo ld -m elf_i386  -Ttext 0xc0001500 -e main -o kernel/kernel.bin kernel/main.o lib/kernel/print.o

写入虚拟内存

sudo dd if=/home/cooiboi/bochs/kernel/kernel.bin of=/home/cooiboi/bochs/boot/hd60M.img bs=512 count=200 seek=9 conv=notrunc
(base) user@ubuntu:/home/cooiboi/bochs$ sudo dd if=/home/cooiboi/bochs/kernel/kernel.bin of=/home/cooiboi/bochs/boot/hd60M.img bs=512 count=200 seek=9 conv=notrunc
5+1 records in
5+1 records out
2820 bytes (2.8 kB, 2.8 KiB) copied, 0.000134415 s, 21.0 MB/s

启动Bochs

sudo bin/bochs -f boot/bochsrc.disk
(base) user@ubuntu:/home/cooiboi/bochs$ sudo bin/bochs -f boot/bochsrc.disk

在这里插入图片描述
在这里插入图片描述

整形字符串打印

整形字符打印方式和字符串打印类似,这里这列举出关键步骤。

  • 修改/home/cooiboi/bochs/lib/kernel目录下print.S和print.h文件

  • 编译print.S

  • 修改main.c文件同时对其进行编译
    在这里插入图片描述

  • 链接 main.o 和 print.o

  • 写入虚拟内存

  • 启动Bochs

sudo bin/bochs -f boot/bochsrc.disk

在这里插入图片描述
在这里插入图片描述

参考资料

  • 《操作系统真象还原》
  • 《操作系统真象还原》第六章 ---- 开启c语言编写函数时代 首挑打印函数小试牛刀 费心讨力重回gcc降级 终尝多日调试之喜悦
  • 《操作系统-真象还原》阅读总结/遗憾离场/加倍努力 出人头地

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148873.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TEE 背景知识

TEE 背景 计算机世界的安全&#xff0c;是保护计算机系统和网络免受攻击者的攻击&#xff0c;这些攻击可能导致未经授权的信息泄露、窃取或损坏硬件、软件或数据&#xff0c;以及它们所提供的服务的中断或误导。更多参考 Computer_security 1 安全是什么 谈安全&#xff0c;…

28.0:Combit LIST LABEL Reporting for Delphi Crack

作为 Delphi 开发人员的优势&#xff1a; 将 VCL 组件直接集成到 Embarcadero IDE 中 免版税报表设计器 交互式预览等 使用综合报表对象 Delphi 和所有其他相关语言和开发环境的报告工具。 将列表和标签集成到 Embarcadero RAD Studio List & Label 的 VCL 组件编译并直接…

HTML与CSS基础(八)—— CSS布局(定位、装饰、选择器拓展)

目标能够说出 定位 的常见应用场景 能够说出 不同定位方式 的特点 能够使用 子绝父相 完成元素水平垂直案例 能够写出三种常见的 光标类型&#xff08;cursor&#xff09; 能够使用 圆角边框 属性完成 正圆 和 胶囊按钮 效果 能够说出 display 和 visibility 让 元素本身隐藏 的…

【java查漏补缺】File类的使用

File类可以用来处理文件数据&#xff0c;比如使用list()方法可以获得某个文件夹下面的所有文件名。 File类的list()方法有一个含有一个参数的重载&#xff0c;在调用该方法的时候需要传入一个FilenameFilter对象&#xff0c;这样便可以进行文件名过滤。 我们先来看一下list()…

GJB 5000B二级-PP项目策划

一、主要变化情况 合并10项(绿色)、修订3项(蓝色)、删除1项(红色) 新增的主要内容 基于A版标准“项目策划”、“集成项目管理”、“定量项目管理”三个过程域中有关项目策划实践的内容来识别,没有新增实践,只增加了以下两个要求: 1、增加软件项目和设备/系统生存周…

Java线程之中断方法

interrupt()方法介绍interrupt() 给目标线程发送一个中断信号&#xff0c;同时将目标线程的中断标志设置为true。至于目标线程是否做出响应&#xff0c;需要看目标线程是否有对应的中断业务逻辑。场景1&#xff1a;假设&#xff0c;你是一个工厂的老板&#xff08;main线程&…

C++类和对象(下)

目录 初始化列表 explicit关键字 Static成员 友元 友元函数 友元类 匿名对象 内部类 初始化列表 初始化列表是以冒号开始&#xff0c;以逗号分割的成员列表&#xff0c;每一个成员变量后面跟一个放在括号中的初始值或表达式。&#xff08;代码演示以日期类为例&#xff…

【实现QQ登录界面 Objective-C语言】

一、实现QQ登录界面 1.实现这样的QQ登录界面 1.实现这样的QQ登录界面 2.首先,分析一下,这个界面里,都有哪些控件 是不是两个Label,两个TextField文本框,1个Button吧 3.先拖1个Label上来 再拖1个TextField文本框上来,在这个Label右边, 然后选中这两个控件, 按住o…

Altium Designer 超详细学习教程——印制电路板基础知识

在介绍Altium Designer软件使用办法之前先介绍下印制电路板的基础知识&#xff0c;不管是画图还是绘制PCB最终目的都是为了制作电路板&#xff0c;因此了解PCB的基础知识很有必要。 1.1印制电路板概述 1.1.1印制电路板结构 在进行PCB设计时&#xff0c;需要先对印制电路板的…

【Linux】对于make/Makefile的使用

本文目录 背景简介 细说关于make命令和makefile文件&#xff1a; 使用方法 为什么执行的指令是make和make clean呢&#xff1f; gcc如何判断文件是否需要重新执行&#xff1f; 背景简介 一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&…

064-Tcp/IP通讯使用ServerSocket及Server实现多人在线聊天项目实训

【上一讲】063-Tcp/IP通讯使用ServerSocket及Server实现多人在线聊天_CSDN专家-赖老师(软件之家)的博客-CSDN博客 本文主要讲解使用ServerSocket,Socket类实现多人同时在线聊天的网络通讯程序,主要功能及技术如下: 1.使用ServerSocket,Socket类实现网络通讯功能; 2.使用…

【go语言之websocket】

go语言之websocket写在前面服务端msggetConnUpgradeNewWsConnectionNextWriterwriteread客户端抓包表现总结写在前面 之前的文章都是介绍的是http的使用&#xff0c;这里主要介绍的是websocket,主要是解决长连接场景下的使用。这里概念不多说&#xff0c;网上很多&#xff0c;…

Ajax篇-前后端交互, 接口文档, ajax, axios, fetch,Postman工具

前后端交互接口文档请求方法区分方式GETPOST从语义上区分偏向于查询&#xff08;获取数据....&#xff09;偏向于提交数据(注册,修改,删除...)安全性显示的携带参数,参数是直接拼接在请求地址之后,安全性较差,隐私性差隐式的携带参数,不会在请求地址上显示,安全性好,以JSON格式…

网络虚拟化基本架构

文章目录架构概述架构图核心组件OpenFlow SwitchPipelineFlow Table EntryInstructionOpenFlow Switch Protocol测试验证Pipeline流表项间流程流表间流程Flow Table EntryInstructionsSwitch ProtocolFaucet架构概述 我们知道网络虚拟化的主要目标就是让报文可以在虚拟机之间进…

Windows Anaconda YOLOv3环境部署--2023年1月8日

时效性&#xff1a; 2023年1月8日 目录摘要1 使用 Anaconda 创建虚拟环境2 安装官方要求的依赖库3 验证安装 | 执行 detect.py 示例代码Key already registered with the same priority摘要 网好的可以直接参考官方文档安装&#xff0c;遇到安装报错和网络问题可以参考本文 本地…

网络安全等级保护定级指南 范围

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 网络安全等级保护 为了配合《中华人民共和国网络安全法》的实施&#xff0c;适应云计算、移动互联、物联网、工业控制和大数据等新技术、新应用情况下网络安全等…

Spring Cloud OpenFeign入门示例

简介 Feign Feign是一个声明性web服务客户端。让编写Web服务客户端变得非常容易&#xff0c;只需创建一个接口并在接口上添加注解即可。让http远程调用就像接口调用一样简单。&#xff08;远程http调用的工具有很多&#xff0c;HttpClient、OKHttp、Spring Boot中的RestTempl…

2023新年红包,兔年HTML红包页面代码【2023新年快乐_附源码】

文章目录一.新年红包&#xff0c;兔年HTML红包页面1.1 资源获取和效果预览二.代码讲解&#xff08;Html文件&#xff09;三.Html文件代码展示&#xff08;需要全部源码请到文章开头链接处下载&#xff09;一.新年红包&#xff0c;兔年HTML红包页面 1.1 资源获取和效果预览 1.…

【Nacos】- Mac-M1下Nacos安装及Nacos启动报错“have ‘x86_64’,need ‘arm64e‘”

Nacos安装及Nacos启动报错“have ‘x86_64’,need arm64e”nacos下载启动nacos问题描述解决方案1、下载安装x86架构的jdk2、更换nacos版本&#xff1a;我这是更换为1.4.2的nacos下载 下载地址&#xff1a;https://github.com/alibaba/nacos/releases 根据自己的工具及需要版本…

LINUX 动态库的版本控制

Linux库文件名的描述版本信息library filename lib <libaray name> .so <libarary version information>库版本信息通常使用以下格式&#xff1a;dynamic libarary version information <M>.<m>.<p>其中&#xff0c;M用一位或多位数字表示库…