一步步编写操作系统 76 用汇编语言编写字符打印函数

之前咱们介绍显卡上那么多的寄存器终于发挥用处了,我们看看前文中介绍的表CRT Controller Data Registers中索引为0Eh的 Cursor Location High Register寄存器和索引为0Fh的Cursor Location Low Register寄存器,这两个寄存器都是8位长度。分别用来存储光标坐标的低8位和高8位地址。

访问CRT controller寄存器组的寄存器,需要先往端口地址为0x3D4的Address Register寄存器中写入寄存器的索引,再从端口地址为0x3D5的Data Register寄存器读、写数据。

接着解释之前的代码(本文是连载,没看过前面,估计本节是蒙逼的)

 1 TI_GDT equ 02 RPL0 equ 03 SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL045 [bits 32]6 section .text7 ;------------------------ put_char -----------------------------8 ;功能描述:把栈中的1个字符写入光标所在处9 ;-------------------------------------------------------------------10 global put_char11 put_char:12 pushad ;备份32位寄存器环境13 ;需要保证gs中为正确的视频段选择子,;为保险起见,每次打印时都为gs赋值14 mov ax, SELECTOR_VIDEO ; 不能直接把立即数送入段寄存器 15 mov gs, ax1617 ;;;;;;;;; 获取当前光标位置 ;;;;;;;;;18 ;先获得高8位19 mov dx, 0x03d4 ;索引寄存器20 mov al, 0x0e ;用于提供光标位置的高8位21 out dx, al22 mov dx, 0x03d5 ;通过读写数据端口0x3d5来获得或设置光标位置23 in al, dx ;得到了光标位置的高8位24 mov ah, al2526 ;再获取低8位27 mov dx, 0x03d428 mov al, 0x0f29 out dx, al30 mov dx, 0x03d531 in al, dx3233 ;将光标存入bx34 mov bx, ax35 ;下面这行是在栈中获取待打印的字符36 mov ecx, [esp + 36] ;pushad压入4×8=32字节,;加上主调函数4字节的返回地址,故esp+36字节37 cmp cl, 0xd ;CR是0x0d,LF是0x0a38 jz .is_carriage_return39 cmp cl, 0xa40 jz .is_line_feed4142 cmp cl, 0x8 ;BS(backspace)的asc码是843 jz .is_backspace44 jmp .put_other

在代码第17~31行用来获取光标值,先在第19~21行设置待操作的寄存器索引,我们先获取的是坐标的高8位,所以要将索引0x0e写入Address Register寄存器,其端口为0x03d4。

确定了要操作的寄存器是Cursor Location High Register后,我们在第22~24行通过Data Register寄存器,其端口是0x3d5,将坐标读入到al寄存器,由于al中是坐标的高8位,所以第24行将其存储在ah寄存器。也许您心存疑惑,既然要把坐标的高8位存到寄存器ah中,为什么不把in指令中的al换成ah,变成in ah, dx?还多捣腾一次干吗?真的抱歉,对于in指令,如果源操作是8位寄存器,目的操作数必须是al,如果源操作数是16位寄存器,目的操作数必须是ax。

第26~32行用同样的方法获取到坐标的低8位,至此,寄存器ax中是光标完整的16位坐标值。

第35行是将光标值从ax寄存器中复制到bx,这么做的原因是习惯用寄存器bx做基址寻址,还记得吗,在16位实模式下基址寄存器必须是bx或bp,变址必须是寄存器si或di。在32位保护模式下没必要这么做了,基址和变址寄存器可以是全部的32位的通用寄存器,就是刚才用pushad指令压入的那8个,忘了往上翻翻。以后的处理都要基于bx寄存器了,在此知道bx现在已经是光标坐标值就行了,它是下一个可打印字符的位置。

第36行是获取栈中压入的字符的ascii码,也就是待打印的字符,这是1字节的数据。栈中除了调用put_char函数的返回地址占4字节外,还有最开始的pushad指令压入的8个32位的通用寄存器共32字节的数据,所以待打印的字符在栈顶偏移36字节的位置。

之后的第36~44行开始判断参数是什么字符,咱们这里只把回车符CR(carriage_return)、换行符LF(line_feed)和退格键backspace当做不可见字符,按照其实际控制意义来处理,其它字符暂时一律认为是可见字符。回车符的ascii码是0xd,换行符的ascii码是0xa,我们这里的处理是,不管参数是回车符,还是换行符,一律按我们平时所理解的回车换行符(CRLF)处理(linux中就把换行符处理成回车+换行),即这两个动作的合成:光标回撤到行首+换到下一行。

本文是连续剧哦,所以得看过之前的文章才行。下班

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

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

相关文章

【人工智能课程实验】 - 利用贝叶斯分类器实现手写数字 的识别

读入数据与预处理 因为老师给的文件无法直接读取&#xff0c;故从官网导入数据&#xff1a; 官网链接&#xff1a;http://www.cs.nyu.edu/~roweis/data.html 导入数据之后要对MATLAB文件进行读入&#xff1a; datasio.loadmat(trainfile) 对文件type一下&#xff1a; ty…

一步步编写操作系统 77 内联汇编与ATT语法简介

内联汇编 之前和大家介绍过了一种汇编方法&#xff0c;就是C代码和汇编代码分别编译&#xff0c;最后通过链接的方式结合在一起形成可执行文件。 另一种方式就是在C代码中直接嵌入汇编语言&#xff0c;强大的GCC无所不能&#xff0c;咱们本节要学习的就是这一种&#xff0c;它…

【Python学习】内置函数(不断更新)

关于常用在for循环中的range函数 python range() 函数可创建一个整数列表&#xff0c;一般用在 for 循环中。 函数语法 range(start, stop[, step]) 参数说明&#xff1a; start: 计数从 start 开始。默认是从 0 开始。例如range&#xff08;5&#xff09;等价于range&#…

【Python学习】 简单语法与常见错误(持续更新)

关于单引号和双引号 当输出的字符串内部没有单引号的时候&#xff0c;外面可以用单引号&#xff0c; 但是如果内部有了单引号&#xff0c;那么外部只能用双引号。 dict {Name: Zara, Age: 7, Class: First} print(dict) print (dict[Name]: , dict[Name]) print ("dic…

一步步编写操作系统 78 intel汇编与ATT汇编语法区别

本节咱们介绍下intel汇编语法和at&t汇编语法的区别。 以上表中未列出这两种语法在内存寻址方面的差异&#xff0c;个人觉得区别还是很大的&#xff0c;下面单独说说。 在Intel语法中&#xff0c;立即数就是普通的数字&#xff0c;如果让立即数成为内存地址&#xff0c;需要…

重读经典:《Masked Autoencoders Are Scalable Vision Learners》

MAE 论文逐段精读【论文精读】这一次李沐博士给大家精读的论文是 MAE&#xff0c;这是一篇比较新的文章&#xff0c;2021年11月11日才上传到 arXiv。这篇文章在知乎上的讨论贴已经超过了一百万个 view&#xff0c;但是在英文社区&#xff0c;大家反应比较平淡一点&#xff0c;R…

【Python学习日志】 - Numpy包

NumPy是什么&#xff1f; 使用Python进行科学计算的基础包&#xff0c;在数据分析的时候比较常用到矩阵计算。这时太多的Np属性不记得&#xff0c;所以方便自己使用把一些常用的Np属性汇总记录一下使用的时候方便查找。 ndarray.ndim 阵列的轴数&#xff08;尺寸&#xff09;…

SQL Server:触发器详解

SQL Server&#xff1a;触发器详解 1. 概述2. 触发器的分类3. Inserted和Deleted表4. 触发器的执行过程5. 创建触发器6. 修改触发器&#xff1a;7. 删除触发器&#xff1a;8. 查看数据库中已有触发器&#xff1a;9. “Instead of”相关示例:10. “After”触发器11. 参考资源 1…

详解协同感知数据集OPV2V: An Open Benchmark Dataset and Fusion Pipeline for Perception with V2V Communication

在《详解自动驾驶仿真框架OpenCDA: An Open Cooperative Driving Automation Framework Integrated with Co-Simulation》 一文中介绍了自动驾驶仿真框架 OpenCDA。本文将介绍论文作者另一篇最新工作 OPV2V&#xff0c;论文收录于 ICRA2022。 OPV2V 数据集主要 feature 有&…

【Python学习】 - 如何在Spyder中弹出plot绘图窗口而不是在Console中绘图

依次选择这几项&#xff1a; 点击ok确认。 注意&#xff1a;点击ok之后不会立即生效&#xff0c;重启Spyder之后才会生效

mysql系列:加深对脏读、脏写、可重复读、幻读的理解

关于相关术语的专业解释&#xff0c;请自行百度了解&#xff0c;本文皆本人自己结合参考书和自己的理解所做的阐述&#xff0c;如有不严谨之处&#xff0c;还请多多指教。 **不可重复读的重点是修改: **同一事务&#xff0c;两次读取到的数据不一样。 幻读的重点在于新增或者…

重读经典(点云深度学习开山之作):《Deep learning on point clouds for 3D scene understanding》(持续更新中)

本文介绍的是 PointNet 作者的博士论文&#xff1a;3D场景理解中的点云深度学习。从上图可以看到&#xff0c;整个博士论文主要贡献有两块&#xff1a;一是点云深度学习的网络架构&#xff08;PointNet 和 PointNet&#xff09;&#xff1b;二是在3D场景理解中的应用&#xff0…

【Python学习】 - plt画图时,添加标题的中英文问题

默认是只能用中文&#xff0c;如果添加了中文标题&#xff0c;则会输出一堆乱码&#xff0c;解决方法就是加上下面这两行代码。 plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus] False

Coursera自动驾驶课程第17讲:An Autonomous Vehicle State Estimator

在第16讲《Coursera自动驾驶课程第16讲&#xff1a;LIDAR Sensing》我们学习了自动驾驶目前常用的3D 传感器&#xff0c;激光雷达&#xff0c;了解了激光雷达的工作原理&#xff0c;掌握了对点云数据的操作以及如何使用点云配准方法来进行汽车定位。 回顾一下&#xff0c;在本…

!何为脏读、不可重复读、幻读

2.0、前言 事务的隔离性是指多个事务并发执行的时候相互之间不受到彼此的干扰的特性&#xff0c;隔离性是事务ACID特性中的I&#xff0c;根据隔离程度从低到高分为Read Uncommitted&#xff08;读未提交&#xff09;&#xff0c;Read Committed&#xff08;读已提交&#xff0…

【Python学习】 - 解决DataFrame占用内存过大问题

这篇文章原文出自kaggle&#xff0c;文中给出了reduce_mem_usage方法可以用来自动缩减dataframe占用空间 这篇notebook展示了通过使用更合理的数据类型来减少dataframe的内存使用量 方法如下&#xff1a; 迭代每一个column 检查column是否为数字型 检查column是否可以用inte…

【转】JPA、Hibernate和Mybatis区别和总结

很多人都用过java的数据库连接池C3P0&#xff0c;但官方没有说明名称的由来。 据传闻&#xff1a;连接池作者是《星球大战》迷&#xff0c;C3P0就是其中的一个机器人&#xff0c;并且这个名称中包涵connection 和pool的单词字母。因此叫这个名字&#xff08;根据网友提醒&…