当前位置: 首页 > news >正文

汇编系列03-不借助操作系统输出Hello World

每天进步一点点,加油!

上一节,我们通过汇编指令,借助操作系统的系统调用实现了向标准输出打印Hello world。这一节我们打算绕过操作系统,直接在显示屏幕上打印Hello world。

计算机的启动过程

当我们给计算机加电启动的时候,它的CPU芯片引脚会自动将它的CS和IP寄存器设置成固定的值。比如8086处理器加电的时候,CS会被设置为0xFFFF,IP会被设置为0x0000。

CS寄存器是代码段寄存器,IP是指针寄存器(指向CPU将要执行的下一条指令的内存地址),真正要执行的指令的物理内存地址由CS寄存器的值左移4位(十六进制的一个0),加上IP寄存器中的值得到。当时8086这么设计是为了在16位寄存器的CPU上实现20位地址空间的内存寻址(即1MB)。

后续的80286、80386等为了兼容8086(在8086上可以运行的程序到升级后的CPU上仍然可以执行),都是遵从这个约定,然后会从实模式切换到保护模式(实模式下,程序中的内存地址就是物理内存地址,保护模式下的程序中的内存地址是逻辑地址,和物理内存地址有映射关系,但那已经是运行时决定的)。

计算机加电完的时候,CS:IP寄存器指向的指令所在的物理内存地址会是BIOS中固化的程序。BIOS即基本输入输出系统的意思,所谓的基本,是指它能做的事情很有限,毕竟BIOS程序很小,它通常用于将操作系统的前面部分装载进内存中(操作系统后边的部分,由操作系统自己装载)。

现在的操作系统基本上都保存在硬盘磁盘中,BIOS会从磁盘的0面0道1扇区将其中的指令读取到内存中执行。这个扇区也叫主引导扇区

如果我们在主引导扇区中写入我们的可执行程序(比如汇编文件经过汇编器编译后得到的二进制文件),那么就可以让CPU直接执行我们的二进制程序,而不用经过操作系统了,这正是我们向屏幕打印Hello, world的好时机啊。

使用VirtualBox虚拟机

前面说过,我们可以将自己的二进制可执行程序写到硬盘的主引导扇区中,让BIOS将我们的程序拷贝到内存中进行执行。
我们打算在虚拟机中模拟这一流程。
我们在虚拟机中可以创建虚拟硬盘,它其实是我们宿主机器上的文件,比如VHD格式的虚拟硬盘文件。这样我们在宿主机上向这个文件中写入数据,然后让虚拟机将它作为磁盘使用,这样不就可以在虚拟机刚启动的时候,用它的CPU执行我们的二进制可执行文件了么?

创建VHD格式虚拟硬盘文件

在管理->工具中创建虚拟硬盘,选择VHD格式:
在这里插入图片描述
下一步,选择预分配大小,而不是在不够用的时候动态增加的:
在这里插入图片描述设置好路径和大小:
在这里插入图片描述然后Finish完成。

Hello world汇编文件

hello.asm源码(代码稍后会解释):

mov ax,0xb800
mov ds,ax
mov byte [0x00],'H'
mov byte [0x01],0x74
mov byte [0x02],'e'
mov byte [0x03],0x74
mov byte [0x04],'l'
mov byte [0x05],0x74
mov byte [0x06],'l'
mov byte [0x07],0x74
mov byte [0x08],'o'
mov byte [0x09],0x74
mov byte [0x0a],','
mov byte [0x0b],0x74
mov byte [0x0c],' '
mov byte [0x0d],0x74
mov byte [0x0e],'w'
mov byte [0x0f],0x74
mov byte [0x10],'o'
mov byte [0x11],0x74
mov byte [0x12],'r'
mov byte [0x13],0x74
mov byte [0x14],'l'
mov byte [0x15],0x74
mov byte [0x16],'d'
mov byte [0x17],0x74jmp $
times 510-($-$$) db 0 
db 0x55,0xaa

通过nasm -f bin hello.asm -o hello.bin将文件汇编成二进制文件。
通过dd if=hello.bin of=hello.vhd bs=512 count=1 conv=notrunc命令将可执行文件复制到刚才创建的VHD文件中(bs表示bytes即字节数,count=1表示之拷贝1个block, notrunc表示do not truncate the output file)。
dd命令的参数含义,可以通过man dd查看:
在这里插入图片描述

刚才两个步骤的执行结果如下:
在这里插入图片描述

启动虚拟机输出Hello world

控制,新建虚拟机,选择Hard Disk为我们刚才创建的VHD文件:
在这里插入图片描述给虚拟机起个名字(不用管虚拟机的类型和版本,因为我们不是通过ISO文件启动的):
在这里插入图片描述
启动虚拟机:
在这里插入图片描述虚拟机的开机界面上打印出了红色的"Hello, world":
在这里插入图片描述

汇编程序的解释

我们已经实现了绕过操作系统向显示器屏幕上打印Hello world,那么hello.asm中的代码分别是什么意思啊?
mov ax,0xb800表示将ax寄存器设置为0xb800,mov ds,ax表示将ax寄存器中的内容,也就是0xb800移动到ds寄存器(数据段寄存器)中(注意,汇编语言不支持将立即数直接mov到段寄存器中,必须经过通用寄存器,如ax的转移)。
之所以这么设置,是因为8086启动的时候,会将内存地址空间中的0xb8000到0xbffff的空间留给显卡的显存。
注意:CPU能够访问的内存地址空间中,可不完全都是我们说的内存条,还有显卡的显存也在内存地址空间中。
等等,我们将0xb800赋值给ds,但是我们说的显存空间是从0xb8000开始的,我们是少赋值了一个0么?并不是,因为我们汇编代码中后边的mov都是基于ds的,比如mov [0x00],'H'其实相当于mov [ds:0x00],'H',ds左移4bit,也就是十六进制的一个0之后,再加上偏移量才是真正的内存地址。
mov [偏移量],0x74表示的字符的显示颜色是白底红字。这样字符占用1个字节,颜色占用1个字节,共2个字节用于表示一个字符。
然后我们就将Hello, world这个字符串中的每个字符都mov到0xb8000开始的内存空间上。

在汇编中,$表示当前行的内存地址,$$表示文件中的第一行的内存地址。
jmp $表示跳转到这个内存地址(该行编译后的内存地址)取指令执行,而它的指令又是跳转到这个地址,所以无限循环下去了。因为我们之作了打印Hello, world这一件事,不需要CPU做别的事情了,就让它陷入死循环了。
times 510-($-$$) db 0的意思是将该行内存地址填充0,填充(510-前面有内容字节数)次。
db 0x55,0xaa的意思是可执行文件的最后两个字节是0x55,0xaa,这是主引导扇区(512字节)的要求,最后2个字节必须是这两个,否则就认为主引导扇区有问题。

这样,我们的汇编程序就是要求CPU在显存开始的地址中拷贝Hello, world字符串,然后陷入死循环。程序后边填充0和追加那两个特殊字符,只是为了让二进制可执行文件能够被认为是合法的主引导扇区文件,大小是512字节,后两个字节是符合规定的。


参考资料:
1.《x86汇编语言 从实模式到保护模式》(第2版)

相关文章:

汇编系列03-不借助操作系统输出Hello World

每天进步一点点,加油! 上一节,我们通过汇编指令,借助操作系统的系统调用实现了向标准输出打印Hello world。这一节我们打算绕过操作系统,直接在显示屏幕上打印Hello world。 计算机的启动过程 当我们给计算机加电启…...

TPU编程竞赛系列|算能赛道冠军SO-FAST团队获第十届CCF BDCI总决赛特等奖!

近日,第十届中国计算机学会(CCF)大数据与计算智能大赛总决赛暨颁奖典礼在苏州顺利落幕,算能赛道的冠军队伍SO-FAST从2万余支队伍中脱颖而出,获得了所有赛道综合评比特等奖! 本届CCF大赛吸引了来自全国的2万…...

【C++】AVL树,平衡二叉树详细解析

文章目录前言1.AVL树的概念2.AVL树节点的定义3.AVL树的插入4.AVL树的旋转左单旋右单旋左右双旋右左双旋AVL树的验证AVL树的删除AVL树的性能前言 前面对map/multimap/set/multiset进行了简单的介绍,在其文档介绍中发现,这几个容器有个共同点是&#xff1…...

C/C++开发,无可避免的多线程(篇四).线程与函数的奇妙碰撞

一、函数、函数指针及函数对象 1.1 函数 函数(function)是把一个语句序列(函数体, function body)关联到一个名字和零或更多个函数形参(function parameter)的列表的 C 实体,可以通过返回或者抛…...

elisp简单实例: taglist

从vim 转到emacs 下,一直为缺少vim 中的tablist 插件而感到失落. 从网上得到的一个emacs中的taglist, 它的功能很简陋,而且没有任何说明, 把它做为elisp的简单实例,供初学者入门倒不错,我给它加了很多注释,帮助理解, 说实话,感觉这百行代码还是挺有深度的,慢慢体会,调试才会有收…...

Azure AI基础到实战(C#2022)-认知服务(3)

目录 OpenFileDialog 类上一节代码的API剖析ComputerVisionClientExtensions.ReadAsync MethodReadHeaders ClassReadHeaders.OperationLocation Property探索ReadHeaders加上调试代码可用于 Azure 认知服务的身份验证标头使用单服务订阅密钥进行身份验证使用多服务订阅密钥进行…...

aws apigateway 使用restapi集成lambda

参考资料 代理集成,https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html非代理集成,https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/getting-started-…...

HTML基础

HTML 基础 文章目录HTML 基础列表标签无序列表有序列表自定义列表表格标签表格基本标签表格基本结构表格完整结构:合并行和合并列表单标签input 系列标签属性标签text 标签radio 标签 单选框file 标签 文件选择button 标签 按钮input系列标签总结button按钮标签sele…...

ThreadPoolExecutor参数 keepAliveTime allowCoreThreadTimeOut

/*** Timeout in nanoseconds for idle threads waiting for work.* Threads use this timeout when there are more than corePoolSize* present or if allowCoreThreadTimeOut. Otherwise they wait* forever for new work.*/ private volatile long keepAliveTime;等待工作的…...

什么是Hibernate框架?

简单介绍:Hibernate框架是当今主流的java持久层框架之一,是一个开放源码的ORM(Object Relational Mapping,对象关系映射)框架,它对JDBC进行了轻量级的封装,使得JAVA开发人员可以使用面向对象的编…...

指针面试笔试题练习

前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨星光…...

docker(三)仓库的搭建、官方私有仓库的加密和认证

文章目录一、docker仓库二、仓库Registry工作原理三、搭建本地私有仓库四、配置镜像加速器五、私有仓库的加密认证1.非加密下上传拉取2.insecure registry3.仓库加密4.仓库认证一、docker仓库 什么是仓库 Docker 仓库是用来包含镜像的位置,Docker提供一个注册服务器…...

FPGA实现SDI视频编解码 SDI接收发送,提供2套工程源码和技术支持

目录1、前言2、设计思路和框架SDI接收SDI缓存写方式处理SDI缓存读方式处理SDI缓存的目的SDI发送3、工程1详解4、工程2详解5、上板调试验证并演示6、福利:工程代码的获取1、前言 FPGA实现SDI视频编解码目前有两种方案: 一是使用专用编解码芯片&#xff0…...

Android 基础知识4-3.5 RadioButton(单选按钮)Checkbox(复选框)详解

一、RadioButton(单选按钮) 1.1、简介 RadioButton表示单选按钮,是button的子类,每一个按钮都有选择和未选中两种状态,经常与RadioGroup一起使用,否则不能实现其单选功能。RadioGroup继承自LinearLayout&a…...

用代码实现解析解的方式求解_梯度下降法思路_导函数有什么用_接23节---人工智能工作笔记0026

这里24节,25节,介绍了一下人工智能高等数学要学习的一些内容,初步了解了一下,微积分中用到的知识~微分~以及导数这里... 然后接着23节,我们还是继续,走人工智能的主线,先把整体的人工智能的内容学习一遍,然后再去回去看数学知识更有目的性. 然后首先来回顾一下,这里机器学习,其…...

大数据ETL开发之图解Kettle工具

详细笔记参考:https://blog.csdn.net/yuan2019035055/article/details/120409547以下只是简单记录一下我学习过程中的心得3.1.5 JSON输入JSONPath 类似于 XPath 在 xml 文档中的定位,JsonPath 表达式通常是用来路径检索或设置Json的。其表达式可以接受“…...

docker-容器数据卷

Docker挂载主机目录访问如果出现cannot open directory.:Permission denied 解决办法:在挂载目录后多加一个--privileged=true参数即可; 一、介绍 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能绕过Union Fil…...

【C++】类和对象补充知识点

🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、再谈构造函数1.1 构造函数体赋…...

路径规划-人工势场法

一.基本思想 目标点对机器人产生吸引力,障碍物对机器人产生排斥力; 所有力的合成构成机器人的控制律 二. 主要步骤 1.构建人工势场 目标点:吸引势场 障碍物:排斥势场 2.根据人工势场计算力 对势场求偏导 3.计算合力 计…...

20230304学习笔记

1、Mybatis #{}和${}的区别是什么 a、#{}是预编辑处理、是占位符,${}是字符串拼接符。 b、#{}替换为?号,用PreparedStatement来赋值,${}直接替换变量的值,用Statement赋值。 c、#{}在DBMS中、自动加入单引号&#…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...