首页 > 系统相关 >《Linux内核完全注释》(2)

《Linux内核完全注释》(2)

时间:2024-02-20 23:22:56浏览次数:21  
标签:语句 汇编 gcc Linux 程序 注释 编译 内核 寄存器

3 内核编程语言和环境

首先介绍了as86和GNU as汇编程序的语法和使用方法,对GNU C中的内联汇编、语句表达式、寄存器变量和内联函数等C语言扩展内容进行介绍,同时描述了C和汇编函数之间的相互调用机制。

3.1 as86汇编器

是一个可以产生16位代码的汇编器,与之配套的是ld86链接器。其是Bruce Evans编写的Intel 8086和80386的编译程序和链接程序。

3.1.1 as86汇编语法

汇编器的作用事发汇编语言源程序(srcfile)编译成目标文件(objfile)。

 as [option] -o objfile srcfile 

3.1.2 汇编语言程序结构

作者写了一段37行的汇编程序boot.s,该程序是一个简单的引导扇区启动程序,可以直接运行。启动后,会在屏幕第17行、第5列处显示出红色的字符串“Loading system ..”,并且光标移到下一行。
作者还详细介绍了这段汇编代码中的一些小知识点:
1.在汇编中以感叹号!和分号;结尾的语句为注释。
2.‘.globl’是一个伪指令,又可以叫指示符,是帮助编译器编译的。这将告诉编译器后面的操作数可以被编译为全局变量。相同的指示符还有.text .data .bss,分别是代码段、数据段、和未初始化数据段。
3.‘entry start’是告诉编译器,程序将从这边开始。
4.作者还介绍了赋值、跳转、并详细介绍了MOV(寻址)的一些用法等,这些可以帮助以前不了解汇编的读者。

3.1.3 as86汇编语言程序的编译和链接

使用as86命令进行编译,生成目标文件,使用ld86进行链接,去掉符号信息。最后使用dd命令将最终文件,写入软盘或者Image盘。

3.1.4 as86和ld86使用方法和选项

想要尝试编译那些古老程序的读者可以去了解一下这章,介绍了这两个命令。

3.2 GNU as 汇编

“上节介绍的 as86 汇编器仅用于编译内核中的 boot/bootsect.s 引导扇区程序和实模式下的设置程序boot/setup.s。内核中其余所有汇编语言程序(包括 C 语言产生的汇编程序)均使用 gas 来编译,并与 C语言程序编译产生的模块链接。”

3.2.1 编译使用as汇编语言写的程序

gas应该就是GNU as。
使用方法为as 【选项】【-o objfile】【srcfile.s】
其编译语法使用AT&T系统V的汇编语法,为了与gcc编译的程序兼容。

3.2.x

3.2.2介绍了gas汇编语言,及其基本语法。
3.2.3介绍了指令语句、操作数和寻址的使用方法。
3.2.4是关于区与重定位。
3.2.5是关于gas汇编中符号的使用方法。
3.2.6介绍了20个汇编命令(伪指令)
3.2.7介绍如何使用as编写16位代码
3.2.8是AS汇编器的命令行选项
这一块内容主要是关于as汇编语言和as汇编器的,内容难度仅限于基本看懂内核代码中的汇编部分。本人不熟悉汇编语言,现在用的也比较少。

3.3 C语言程序

C语言比起汇编语言效率还是高一点。

C语言程序进行编译的时候通常会经过四个处理阶段:预处理阶段、编译阶段、汇编阶段、链接阶段。
预处理阶段对C语言程序中的指示符和宏进行替换,删除注释,输出纯C文件。编译是用gcc将纯C编译成汇编程序。汇编是用as汇编器将as汇编编译成.o目标文件。链接是使用ld链接器把各个.o文件和.a库文件链接起来,生成一个可执行文件。这个过程可以调用gcc命令进行执行。gcc【选项】【-o outfile】infile ... -S选项只会执行到汇编阶段前,生成.s汇编文件。-c选项不会执行链接,只生成.o目标文件。

当然,C语言程序也可以嵌入汇编,基本格式为:
asm("汇编语句"
:输出寄存器
:输入寄存器
:会被修改的寄存器
);
除第1行以外,后面带冒号的行若不使用就都可以省略。“asm”是内联汇编语句关键词;“汇编语句”是你写汇编指令的地方;“输出寄存器”表示当这段嵌入汇编执行完之后,哪些寄存器用于存放输出数据。此地,这些寄存器会分别对应一 C 语言表达式值或一个内存地址;“输入寄存器”表示在开始执行汇编代码时,这里指定的一些寄存器中应存放的输入值,它们也分别对应着一 C 变量或常数值。“会被修改的寄存器”表示你已对其中列出的寄存器中的值进行了改动, gcc 编译器不能再依赖于它原先对这些寄存器加载的值。如果必要的话, gcc 需要重新加载这些寄存器。因此我们需要把那些没有在输出/输入寄存器部分列出,但是在汇编语句中明确使用到或隐含使用到的寄存器名列在这个部分中。表3-4是常用寄存器加载代码说明。
之后说明了一些例子,讲解gcc是如何处理这些汇编语句。gcc自己也会对汇编语句进行优化,避免执行那些重复的语句。当然如果不想代码被gcc优化,就需要在 asm 符号后面添加关键词volatile。

圆括号中的组合语句,即形如”({...})”的语句,可以在 GNU C 中用作一个表达式使用。
当然,人们通常不会象上面这样写语句,这种语句表达式通常都用来定义宏。例如内核源代码init/main.c 程序中读取 CMOS 时钟信息的宏定义:
69 #define CMOS_READ(addr) ({ \ // 最后反斜杠起连接两行语句的作用。
70 outb_p(0x80|addr,0x70); \ // 首先向 I/O 端口 0x70 输出欲读取的位置 addr。
71 inb_p(0x71); \ // 然后从端口 0x71 读入该位置处的值作为返回值。
72 })

GNU 对 C 语言的另一个扩充是允许我们把一些变量值放到CPU寄存器中,即所谓寄存器变量。这样CPU就不用经常花费较长时间访问内存去取值。
register int res asm("ax");
这里 ax 是变量 res 所希望使用的寄存器。定义这样一个寄存器变量并不会专门保留这个寄存器不派其他用途。在程序编译过程中,当 gcc 数据流控制确定变量的值已经不用时就可能将该寄存器派作其他用途,而且对它的引用可能会被删除、移动或被简化。

在程序中,通过把一个函数声明为内联( inline)函数,就可以让 gcc 把函数的代码集成到调用该函数的代码中去。这样处理可以去掉函数调用时进入/退出时间开销,从而肯定能够加快执行速度。达到用空间换取时间的特性。
inline int inc(int *a)
后面介绍了static和inline组合,还有extern和inline的组合的使用注意点。

标签:语句,汇编,gcc,Linux,程序,注释,编译,内核,寄存器
From: https://www.cnblogs.com/HYBZ/p/17777726.html

相关文章

  • Java基础01:注释
    1.注释:1.1.平时编写代码,在代码量比较少的时候,还可以看懂自己写的,但是当项目结构一旦复杂,就需要用到注释1.2.注释不会被执行,是给写代码的人看的1.3.养成注释的好习惯2.java中的注释有三种:2.1单行注释2.2多行注释2.3文档注释1.创建一个......
  • Linux下使用docker部署vue项目
    通过nginx镜像部署关于前端vue项目部署:使用npm打包创建nginx容器dockerrun-d--nameadmin_portal-p9091:80nginx将dist目录下的所有文件拷贝到容器的/usr/share/nginx/html目录下,这个是html文件的默认读取路径dockercp./admin_portal:/usr/share/nginx/html/......
  • linux下部署MySQL服务
    linux下部署MySQL服务1、安装sudo-s调整为root下用户角色运行以下命令安装MySQL,输入Y继续sudoaptinstallmysql-server2、启动systemctlstartmysqld设置MySQL开机自启动(可选)systemctlenablemysqld3、检查运行状态systemctlstatusmysqld4、配置MySQL用户......
  • LInux下wc命令简单使用
    前言利用wc指令我们可以计算文件的Byte数、字数、或列数,如果不指定文件名称,或者所给予的文件名为"-",则wc指令会从标准输入设备读取数据。使用语法如下wc[-clw][--help][--version][文件...]参数如下-c或--bytes或--chars只显示Bytes数。-l或--lines显示行数。-w或--w......
  • 在 Linux 系统上安装 mysql 5.7
    准备工作下载MySQL:下载页面、下载地址创建MySQL用户组、用户、相关目录、日志文件#创建新用户组groupaddmysql#创建用户mysql,指定所属用户组为mysql,禁止其登录useradd-r-gmysql-s/sbin/nologin#创建安装目录(可以自定义,这里以“/usr/local/mysql”为例)mk......
  • Linux 路由操作
    查询路由:sudoiprouteshowsudonetstat-nr添加路由如我需要添加10.0.0.0走wlp0s网卡的命令则是iprouteadd10.0.0.0/8via<网关地址>dev设备名上面的只是临时的路由,需要配置到配置文件里Ubuntu18以上的配置文件在/etc/netplan下的yaml下的文件里:network:versio......
  • linux 中国 xargs 标准化输出参数
     001、[root@pc1tmp]#echo{1..30}|xargsprintf"%02d%03d\n"01002##xargs标准化输出参数0300405006070080901011012130141501617018190202102223024250262702829030 002、[root@pc1tmp]#echo{1........
  • Nginx 在Linux中安装、使用、配置详解
    一、官网下载Nginx官网地址:http://nginx.org/en/download.html我下载的是最新稳定版 二、上传到服务器解压1、上传到指定的服务器地址上传的地址自己决定,我上传到/usr/Nginx。2、解压使用命令:tar-zxvf“你的Nginx压缩包”,我这里是:tar-zxvfnginx-1.24.0.ta......
  • Linux_9 docker教程
    title:(在线学习平台)link:(https://www.acwing.com/)cover:(https://cdn.acwing.com/media/activity/surface/log.png)1.将当前用户添加到docker用户组为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入安装中自动创建的docker用户组(可以参考官方文档):sud......
  • 【转载】linux利用crontab添加定时任务详解
    crontab作用:添加,查询,删除系统计划任务的指令。[root@localhost~]#crontab[选项]选项:   -e:   编辑crontab定时任务   -l:   查询crontab任务   -r:   删除当前用户所有的crontab任务1234512345[root@localhost~]#crontab-e......