理解计算机系统_程序的机器级表示(二):寄存器,操作数,数据传送,程序栈

前言

        以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定

引入

        本书第三章:程序的机器级表示内容的理解,这一章内容以汇编语言为主.汇编语言偏底层,用于系统级别的程序编写.如果不是做系统的,可以不用深入学习.理解汇编语言的关键是理解gcc指令,数据,寄存器,地址等概念.这些概念在C语言中也是很重要的,而且从汇编语言的角度会发现更多细节.

        这章可以作为学习C语言的辅助,明白C语言的运行机制.其中重点关注能优化代码的部分.

        本帖内容为3.4节访问信息

一.寄存器

        本书P119讲了寄存器的演化历史,和指令集历史同步.

        1>寄存器是干什么的?

         大致推导代码执行过程:源代码经编译汇编链接后,成为可执行文件并加载到内存中.可执行文件是十六进制组成的机器码,实际上是一条条的指令,交给CPU执行.

        每条指令有指令码和操作数.例如

movl $0x4050,%eax

         指令码由PC(程序计数器Program Counter)管理,存放着指令地址,执行完一条指令后,自动指向下一条指令的地址.CPU执行相应的指令,作为软件开发者可以不管CPU是怎么完成指令的,因为指令码提供了机器活动的抽象,比如movl这条指令,程序员调用后,将立即数0x4050送到寄存器%eax中.

        指令码的实现由芯片开发人员完成,我们可以设想一下:把一个十六进制数0x4050,送到%eax中,按照二进制0B0100 0000 0101 0000,CPU接到这条指令,把%eax(32位寄存器)中对应的值等于1的位打开,对应值等于0的位关闭.------------这段属于超纲内容,知道他的结果就行了.

        CPU有个特点:只能处理来自寄存器的数据,指令中的操作数必须经寄存器传给CPU.寄存器的作用是把内存的数据调入交给CPU处理;再将CPU处理好的数据交给内存.简而言之,寄存器是用来中转数据的.

        2>认识寄存器

        本书P120画出了x86-64的整数寄存器图,如果想使用汇编语言,这张图挺重要,最好能熟悉.

         简单认识一下寄存器,有64位,32位,16位,8位之分,分别对应四字,双字,字和字节.各自特点如下:

                 64位寄存器特点:以"r"开头,非"d"结尾

                 32位寄存器特点:以"e"开头或者"d"结尾

                 8位寄存器特点:以"l"或者"b"结尾

                  其余是16位寄存器 

         在P120倒数第二段,有关于寄存器指令的特别规则:当这些指令以寄存器为目标时,生成4字节数的指令会把高位4个字节置0.

        说明:指令有以下2个特点:

        1)指令有单个操作数或者两个操作数(3个以上的暂时还没见过)

        2)指令末尾要加上表示操作数字节长度的标识(字节加b,字加w,双字加l,四字加q)

        当第2个操作数为寄存器,且指令以"l"结尾时,高位4个字节将置0.

        3>每个寄存器的作用   

         本书P120最后一段,强调了栈指针%rsp,知名运行时栈的结束位置.P121第一段:有一组标准的编程规范控制着如何使用寄存器来管理栈、传递函数参数、从函数的返回值,以及存储局部和临时数据.(黑体字是原话).这段话表明了寄存器有使用规则,具体怎样使用在3.7节

二.操作数指示符

          操作数的类型有三种:立即数,直接寻址(寄存器寻址和内存寻址),间接寻址(内存地址).为了方便下面的理解:操作数其实是两个类型,立即数和地址

          操作数的抽象模型是这样的:

        以下是直接寻址和间接寻址的示意图 

        

        直接寻址:当标识是寄存器名称或者内存时,实际上表示的是他的数值

        间接寻址:当标识用()括起来的寄存器名称或者内存时,表示以他的数值为地址内的数值.

        由此引出一个非常重要!非常重要的概念

                 内存中的数据都是以地址形式出现(立即数除外)

        从这个结论对前面所学内容做个回顾和对比:

        1.首先是指针的重要性,在C语言等高级语言中,有"变量"的存在.变量是为了方便编写和使用程序的人理解而设置的.CPU不认识变量,他是通过数据地址来运算的.所以变量是地址的代名词

        2.立即数的用途不多,在高级语言中,一般使用枚举来表示常量,避开硬编码,侧面加强了这个概念,突出地址的重要性.

        3.地址传递数据这一机制,由接收方直接寻址或间接寻址来表达传的是值或者指针,非常好用.这句话很拗口,用代码来说明

//以下标记为代码段1
movew $0x1040,0xff00        //把0x1040写入地址0xff00
movew $0x1000,0x1040        //把0x1000写入地址0x1040 
movew 0xff00,%ax            //把0xff00的值0x1040传给寄存器%ax
movew %ax,0x40              //把寄存器%ax里的值传给地址0x40,此时0x40的值等于0x1040
movew (%ax),%rdx            //把寄存器%ax值表示的地址的值传给%rdx,此时%rdx值等于0x1000

         由%ax接收数据后,%ax表示接收到的值,由(%ax)表示值的地址里的值.因此可以忽略数据类型是"变量"还是"指针".这一点细微的差别,能感觉得出比起高级语言中需声明指针,再间接访问数据这种写法来得更好.-------第3点属于思路发散,实际意义没多少,个人感觉创造出"间接寻址"这个概念的人很厉害

        关于操作数指示符的其他内容,可以参看本书P121和P122,并做一做练习题.

三.数据传送指令

        本书P122说了数据传送指令是最频繁使用的指令.回到编程的根本目的---用数据来表示结果.传送指令相当于直接写入结果. 运行程序中各种参数传递,结果回传等,都会用到move指令,所以使用很多.

        笔者把数据传送指令的规则做个归纳和说明

        1>源操作数可以是立即数,寄存器或者内存地址;目的操作数必须是地址

                和上面操作数讲的一样,源操作数用寄存器名称或者内存地址,表示他的数值.目的操作数必须是地址,不能是立即数.以下写法错误

//错误写法
movew 0x40 $0xff00        //目的操作数是立即数

           2>源操作数和目的操作数不能都是地址,如果把一个地址的数据传到另一个地址中,需要经过寄存器,两步转换.

movew 0xff00,%ax            //把0xff00的值传给寄存器%ax
movew %ax,0x40              //把寄存器%ax里的值传给地址0x40

这样写是错的

//以下为错误写法
movew 0xff00,0x40         //不能将一个内存的值直接传给另一个内存地址
//以下是正确写法
movew $0x40 0xff00        //立即数写入内存

                3>寄存器部分的大小必须与指令最后一个字符(b,w,l,q)指定大小匹配(本书P123原话).move指令对于内存地址没有限制

moveb %ax,0xff00    //错误,b表示字节,%ax表示字,大小不匹配
moveb %al,%bl       //正确,寄存器大小匹配

                4>特殊的movl指令:movl指令用于替代movzlq指令.和寄存器特殊运算规则一样,当以寄存器为目的操作数,指令使用movl时,它会将该寄存器的高位4字节设置为0. 

movl %eax,%rdx    //错误,%rdx高4字节位被置0(不可预料后果)

                5>某些寄存器不能被作为目的操作数                

movb $0xf,(%ebx)    //错误,被调用者保留位,不能被写入

====================================内容分割线============================ 

         笔者在看完了move指令的用法,做了相关习题后,确实有些"嫌"汇编语言.他好不好学,好不好用笔者不知道,但就只是一个指令,就有这么多规则要遵守,在写代码段1的时候,还很小心地对地址进行了计算(每个数据占8个字节,因此地址末尾应该是0x00,0x40,0x80,0xc0)

        回到理解汇编语言的初衷,加深对C语言的认识,以及优化代码的基础上去学汇编语言是很好的.但如果可以用高级语言替代,又没有那么大的兴趣去研究的话,相关内容可以考虑不看.

====================================内容分割线============================ 

          P125的3.4.3数据传送示例,有一个地方需要注意,在程序传参的过程中,实际上还发生了一些代码调用.具体要结合程序中上面的代码.

//将xp地址传给寄存器%rdi(第一个参数),这里xp是形参,实际上是实参地址
//将y地址传给寄存器%rsi(第二个参数),这里y是形参,实际上是实参地址
//xp in %rdi的伪代码实现,y in %rsi的伪代码实现
moveq xp地址 %rdi    
moveq y地址 %rsi

 四.程序栈的初识

        本书P127有几句重要的内容(黑体字是原话)

        1>程序栈存放在内存某个区域

        2>栈向下增长

        3>栈指针%rsp保存着栈顶元素的地址

        这里程序栈内容并没有讲栈内内容如何与寄存器产生数据交互.

        重点:栈指针始终指向栈顶,保存着栈顶元素的地址.每当数据压入栈中,栈顶地址值加8(8个字节),每当数据弹出栈,栈顶地址值减8,汇编代码如下

subq $8,%rsp        //数据压栈,栈向下增长,栈顶元素地址减8
addq $8,%rsp        //数据出栈,栈向上增长,栈顶元素地址加8

        栈指针%rsp的作用,就和指向链表首个元素的指针一样(可以访问链表中任意一个元素),获得栈指针可以访问栈内任意元素(每次移动8个字节.),并将其传给寄存器,以使CPU获得数据后执行指令.

小结

        3.4节的内容对理解程序的执行过程还是非常重要的

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

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

相关文章

nginx代理,nginx301跳转,nginx地址重写

ngin代理 假如你的地址是:http://192.168.1.2:8282 你的域名是:www.jjycheng.com 你想访问域名www.jjycheng.com时,实际请求的地址是http://192.168.1.2:8282,但浏览器上的地址不变。 此时,你用到的技术就是请求代理 代理.conf配置 http {server {listen 80; server_na…

看门狗电路设计

看门狗电路设计 看门狗是什么应用架构图TPV6823芯片功能硬件时序图为什么要一般是要保持200个毫秒左右的这种低电平的时间看门狗电路实际应用与条件 看门狗是什么 硬件看门狗芯片&#xff0c;Watch DogTimer&#xff0c;可用于受到电气噪音、电源故障、静电放电等影响(造成软件…

LabVIEW混合控制器质量检测

随着工业自动化水平的提高&#xff0c;对控制器的精度、稳定性、可靠性要求也在不断上升。特别是在工程机械、自动化生产、风力发电等领域&#xff0c;传统的质量检测方法已无法满足现代工业的高要求。因此&#xff0c;开发一套自动化、精确、可扩展的混合控制器质量检测平台成…

怎么编辑图片?这5款工具教你快速编辑

怎么编辑图片&#xff1f;编辑图片是一项既具创意又实用的技能&#xff0c;它不仅能够提升图片的视觉效果&#xff0c;增强信息的传达力&#xff0c;还能激发无限的创作灵感。通过编辑图片&#xff0c;我们可以轻松调整色彩、添加文字、裁剪构图&#xff0c;甚至创造出令人惊叹…

《Linux从小白到高手》理论篇:Linux的系统环境管理

List item 值此国庆佳节&#xff0c;深宅家中&#xff0c;闲来无事&#xff0c;就多写几篇博文。本篇详细深入介绍Linux的系统环境管理。 环境变量 linux系统下&#xff0c;如果你下载并安装了应用程序&#xff0c;很有可能在键入它的名称时出现“command not found”的提示…

【Redis】Redis线程模型

目录 1. Redis 是单线程的&#xff0c;还是多线程的&#xff1f;2. Redis单线程模式是怎么样的&#xff1f;Redis 单线程模式的优势Redis 单线程的局限性Redis 单线程的优化策略 3. Redis采用单线程为什么还这么快4. Redis 6.0 之前为什么使用单线程&#xff1f;5. Redis 6.0 之…

10.1 10.3 图DFS 中等 207 Course Schedule 210 Course Schedule Ⅱ

207 Course Schedule class Solution { public:bool hasCycle(int course ,unordered_map<int,vector<int>>& graph,vector<int>& visitStatus){//正在访问的结点再次被访问&#xff0c;存在环if(visitStatus[course] 1)return true;//该结点已经被…

仪器校准机构提供了资质证明,就能够代表目前的检测能力吗?

最近的一次公司审核打破了我对仪器校准机构能力认证这一独特理论的认识。换句话说&#xff0c;最近参加了公司的质量整合审核&#xff0c;其中之一就是仪器校准机构检测能力审核。根据我平时的经验&#xff0c;我给审核老师提供了CNAS和客户等一系列资质证书&#xff0c;以证明…

PMP--冲刺题--解题--91-100

文章目录 11.风险管理--4.实施定量风险分析--题干场景中提到了“专家”&#xff0c;同时即将开始“量化风险”&#xff0c;因此对应的就是“定量风险分析”中的“专家判断”技术。项目经理应先征求各位专家们的意见&#xff0c;以获取最佳的量化风险实施方案。谋定而后动91、 […

芯片复位电路-RC复位

芯片复位电路-RC复位 MAX809专门的上电复位芯片使用注意芯片间级联复位 看门狗复位注意事项 MAX809专门的上电复位芯片 可以看到这里VTH这个电压值一般是你你电复位芯片供电的90%左右&#xff0c;比如说5V&#xff0c;那这里可能是4.5V。 使用注意 A.复位输出引脚要加上拉电阻…

解决跨域问题

第一种 让后端解决 第二种 通过代理来解决 首先可以先搭建后端接口 解决则参照vue-cli官网 首先新建一个vue.config.js文件 然后在项目的根目录新建两个文件夹 开发环境和生产环境 然后可以使用环境变量 系统会自动识别你是生产环境还是开发环境 然后在封装的axios中配…

【Qt】控件概述 (1)—— Widget属性

控件概述 1. QWidget核心属性1.1核心属性概述1.2 enable1.3 geometry——窗口坐标1.4 window frame的影响1.4 windowTitle——窗口标题1.5 windowIcon——窗口图标1.6 windowOpacity——透明度设置1.7 cursor——光标设置1.8 font——字体设置1.9 toolTip——鼠标悬停提示设置1…

Puppeteer自动化:使用JavaScript定制PDF下载

引言 在现代的Web开发中&#xff0c;自动化已经成为提高效率和减少重复劳动的重要手段。Puppeteer 是一个强大的Node.js库&#xff0c;提供了对无头Chrome或Chromium的控制&#xff0c;可以用于生成网页快照、抓取数据、自动化测试等任务。其中&#xff0c;生成PDF文件是一个常…

cnn突破八(两层卷积核bpnet网络扩展)

cnn突破七中x【&#xff1f;】怎么求&#xff1f;我们举个例子&#xff1a; 接着cnn突破七&#xff1a; hicnn【】来自temphicnn【】2*2最大池化&#xff1a; temphicnn[0]x[i0,j0,5*5方阵]*w1cnn[0-24]&#xff0c; hicnn是5*5的&#xff0c;temphicnn是10*10的&#xff0…

git clone 私有仓库时出现错误 Authentication failed for :xxxxxx

错误信息 remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended…

音频剪辑在线工具 —— 让声音更精彩

你是否曾梦想过拥有自己的声音创作空间&#xff0c;却苦于复杂的音频编辑软件&#xff1f;接下来&#xff0c;让我们一同揭开这些音频剪辑在线工具的神秘面纱&#xff0c;看看它们如何帮助你实现从录音到发布的无缝衔接。 1.福昕音频剪辑 链接直达>>https://www.foxits…

Windows系统编程(三)线程并发

进程与线程 进程&#xff1a;直观的说就是任务管理器中各种正在运行的程序。对于操作系统来说&#xff0c;进程仅仅是一个数据结构&#xff0c;并不会真实的执行代码 线程&#xff1a;通常被称作但并不真的是轻量级进程或实际工作中的进程&#xff0c;它会真实的执行代码。每…

Qwen变体新成员加一,英伟达训练 NVLM-D-72B 视觉大模型

今天&#xff08;2024 年 9 月 17 日&#xff09;&#xff0c;我们推出了前沿级多模态大语言模型&#xff08;LLM&#xff09;系列 NVLM 1.0&#xff0c;它在视觉语言任务上取得了最先进的结果&#xff0c;可与领先的专有模型&#xff08;如 GPT-4o&#xff09;和开放存取模型&…

易图讯军用VR三维电子沙盘系统

深圳易图讯军用VR三维电子沙盘系统是一种集成了虚拟现实&#xff08;VR&#xff09;技术、三维建模技术、大数据分析、实时动态更新以及高度安全可靠的综合性军事指挥平台。该系统通过高精度三维模型真实再现战场环境&#xff0c;为指挥员提供沉浸式体验和交互操作的可能性&…

【黑马点评】0.环境配置--Redis6.2.6和可视化工具在Windows上的安装

黑马点评--0.Redis6.2.6在windows上的环境配置与可视化 0 前言1 下载安装2 解压后运行msi文件3 修改配置文件并打开Redis3.1 修改密码&#xff08;可选&#xff09;3.2 测试 4 Redis可视化&#xff08;可选&#xff09;4.1 Another Redis Desktop Manager下载安装4.2 连接Redis…