【数据结构】汇编语言和机器语言的‘数据结构‘
前言
汇编语言没有像高级语言(如 C#、Java 等)那样直接提供数据结构(如数组、链表、树、栈等),但是可以通过对内存地址和寄存器的操作来实现这些数据结构。汇编语言的核心是直接操控计算机的内存,因此所有数据结构的实现都需要手动管理内存和指针。
下面介绍几种在汇编语言中实现基本数据结构的方式:
1. 数组(Array)
在汇编中,数组通常是通过一组连续的内存单元实现的。可以使用寄存器来存储数组的起始地址,然后通过索引偏移访问数组中的元素。
示例(x86 汇编,使用数组访问):
section .data
array db 10, 20, 30, 40, 50 ; 定义一个字节数组,包含5个元素section .text
global _start
_start:mov esi, array ; 将数组起始地址存入 ESI 寄存器mov al, [esi+2] ; 访问数组的第三个元素(值为30); 此时 al = 30
在这个例子中,array 是一个连续的内存区域,存储了 5 个字节数据。ESI 寄存器用来指向数组的起始地址,[esi+2] 表示访问偏移量为 2 的位置,即第三个元素。
2. 栈(Stack)
在汇编中,栈是一个非常常见的数据结构。栈通常通过 PUSH 和 POP 指令来实现。栈是基于后进先出(LIFO)原则的,即最后压入的数据最先弹出。
示例(x86 汇编,使用栈):
section .text
global _start
_start:mov eax, 10 ; 将值 10 放入 EAX 寄存器push eax ; 将 EAX 的值压入栈中mov eax, 20 ; 将值 20 放入 EAX 寄存器push eax ; 将 EAX 的值压入栈中pop ebx ; 从栈中弹出数据到 EBX 寄存器(值为 20)pop ecx ; 从栈中弹出数据到 ECX 寄存器(值为 10); 此时 ebx = 20, ecx = 10
栈的操作基于 ESP(栈指针寄存器),PUSH 指令将数据压入栈中并更新 ESP,而 POP 指令则从栈顶弹出数据并更新 ESP。
3. 链表(Linked List)
链表在汇编中可以通过指针(内存地址)和数据节点实现。每个节点通常包含一个数据域和一个指向下一个节点的指针域。
示例(链表节点定义):
在汇编中,链表的每个节点可以由两个连续的内存区域来表示,一个存储数据,另一个存储下一个节点的地址。
section .data
node1_data dd 10 ; 节点1的数据
node1_next dd node2 ; 节点1的下一个节点地址node2_data dd 20 ; 节点2的数据
node2_next dd 0 ; 节点2的下一个节点地址(0表示链表结束)
在这个例子中,node1 和 node2 代表链表的两个节点。node1 包含数据 10,并指向下一个节点 node2。node2 的数据为 20,且 node2_next 为 0,表示链表的结尾。
访问链表节点:
可以通过寄存器指向链表节点的地址,并通过偏移量访问数据和下一个节点地址。
4. 队列(Queue)
队列在汇编中可以使用内存数组和两个指针(头指针和尾指针)实现。队列是一种先进先出(FIFO)的数据结构。
示例(队列的实现):
section .data
queue db 5 dup(0) ; 定义一个大小为5的队列(字节数组)
head dw 0 ; 队列头指针,初始化为0
tail dw 0 ; 队列尾指针,初始化为0
在这个队列中,head 和 tail 分别指向队列的头和尾。插入数据时,增加 tail 指针;取出数据时,增加 head 指针。当指针达到数组末尾时,可能需要进行回绕(循环队列)。
小结
汇编语言的数据结构实现依赖于内存管理和寄存器操作,例如:
- 数组:通过内存的连续地址和偏移实现。
- 栈:利用 CPU 的
ESP栈指针及PUSH/POP指令操作。 - 链表:使用内存中的节点地址和指针域来建立节点的链接。
- 队列:通过数组和头尾指针模拟,依靠手动管理指针完成入队、出队操作。
这些数据结构在汇编中都要手动管理指针和内存,灵活性大但难度较高。
机器语言的’数据结构’
在机器语言中,数据结构的存储方式直接依赖于内存地址和 CPU 寄存器。机器语言是最低级别的编程语言,因此它没有内置的数据结构,只能通过直接的内存操作来模拟数据结构的行为。下面是一些机器语言中常见的数据存储和结构组织方式:
1. 基本数据(如整数、字符)
基本数据类型(如整数、字符)通常直接存储在内存地址中。每种数据类型都有固定的位宽,比如:
- 字符(
char):通常用 1 个字节(8 位)表示。 - 整数(
int):可以用 1、2、4、或 8 字节表示,具体取决于系统架构。
示例:
假设一个内存单元存储了一个整数 5,在内存中存储方式如下:
| 地址 | 值 |
|---|---|
| 0x1000 | 05 |
这里,内存地址 0x1000 存储了整数 5。在机器语言中,程序可以直接访问地址 0x1000 来获取该值。
2. 数组
数组在机器语言中表示为一组连续的内存单元。数组的每个元素占用相同的内存空间,因此可以通过起始地址和偏移来访问每个元素。
示例:一个包含 4 个整数的数组,分别为 10, 20, 30, 40。
| 地址 | 值 |
|---|---|
| 0x2000 | 0A |
| 0x2004 | 14 |
| 0x2008 | 1E |
| 0x200C | 28 |
在这个例子中:
- 数组的起始地址是
0x2000。 - 每个整数占用 4 个字节。
- 访问第
i个元素的地址为起始地址 + i * 元素大小。
3. 栈(Stack)
栈是基于内存的“后进先出”(LIFO)结构,通常通过栈指针(例如 ESP 寄存器)管理。栈的数据结构存储在内存中,通常从高地址向低地址增长。每次向栈中添加数据(PUSH),栈指针都会减少;而每次从栈中移除数据(POP),栈指针都会增加。
示例:
假设栈的初始地址为 0x3000,向栈中压入两个整数 10 和 20,栈的结构如下:
| 地址 | 值 |
|---|---|
| 0x2FFC | 10 |
| 0x2FF8 | 20 |
| 0x3000 | ESP (栈顶指针) |
在机器语言中,通过直接操作栈指针来控制数据的入栈和出栈过程。
4. 链表(Linked List)
链表在机器语言中是通过指针来实现的。每个节点包含两部分:数据区域和指针区域。指针区域存储下一个节点的地址。
示例:假设链表有两个节点,分别存储 50 和 100,内存结构如下:
| 地址 | 值 | 说明 |
|---|---|---|
| 0x4000 | 32 | 第一个节点的数据(50) |
| 0x4004 | 0x4008 | 指向下一个节点的地址 |
| 0x4008 | 64 | 第二个节点的数据(100) |
| 0x400C | 0 | 终止指针(0 表示结束) |
在机器语言中,通过读取当前节点的地址,然后访问“指向下一个节点的地址”字段,即可遍历链表。
5. 队列(Queue)
队列在机器语言中可以用循环数组来实现,并使用两个指针来管理:一个指向队列头(front),一个指向队列尾(rear)。队列遵循先进先出(FIFO)原则。
示例:假设队列有 4 个字节的空间,用于存储 2 个数据 60 和 70,内存结构如下:
| 地址 | 值 | 说明 |
|---|---|---|
| 0x5000 | 3C | 队列头(60) |
| 0x5004 | 46 | 队列尾(70) |
在机器语言中,通过移动队列头和尾指针,控制数据的入队和出队。
小结
机器语言中的数据结构是通过直接操控内存地址和寄存器来实现的。没有高级数据结构,只能使用以下方式模拟:
- 基本数据:直接存储在单个内存单元或寄存器中。
- 数组:通过连续的内存单元实现,使用偏移量访问。
- 栈:使用栈指针和 PUSH/POP 操作从高地址到低地址管理数据。
- 链表:每个节点包含数据和指向下一个节点的指针。
- 队列:用循环数组实现,通过头尾指针管理。
相关文章:
【数据结构】汇编语言和机器语言的‘数据结构‘
前言 汇编语言没有像高级语言(如 C#、Java 等)那样直接提供数据结构(如数组、链表、树、栈等),但是可以通过对内存地址和寄存器的操作来实现这些数据结构。汇编语言的核心是直接操控计算机的内存,因此所有…...
hadoop+spark中8088,18080,19888,4040端口页面的区别
在hadoop集群中,本身就有 9870端口,8088端口,19888端口 这三个页面,当使用spark作为计算引擎时,会多出8080,4040,18080这三个页面,页面就很多了,现在明确的辨别一下。 单…...
PDS的主要部件
PDS(配电系统)的主要部件包括去耦电容器、电源调节器、PCB几何结构等。以下是这些主要部件的相关介绍: 去耦电容器:去耦电容器是PDS中不可或缺的组成部分,其主要功能是过滤掉电源线上的噪声和干扰,确保供电…...
(十三)JavaWeb后端开发——MySQL2
目录 1.DQL数据查询语言 1.1基本查询 1.2条件查询 where关键字 1.3分组查询 1.4排序查询 1.5分页查询 2.多表设计 3.多表查询——联查 4.多表查询——子查询 5.MySQL 事务 6.事务管理(事务进阶) 7.MySQL 索引 1.DQL数据查询语言 分为五大…...
MFC图形函数学习06——画椭圆弧线函数
绘制椭圆弧线函数是MFC基本绘图函数,这个函数需要的参数比较多,共四对坐标点。前两对坐标点确定椭圆的位置与大小,后两对坐标确定椭圆弧线的起点与终点。 一、绘制椭圆弧线函数 原型:BOOL Arc(int x1,int y1,int x2,int y2…...
缓存、注解、分页
一.缓存 作用:应用查询上,内存中的块区域。 缓存查询结果,减少与数据库的交互,从而提高运行效率。 1.SqlSession 缓存 1. 又称为一级缓存,mybatis自动开启。 2. 作用范围:同一…...
【数据结构与算法】第9课—数据结构之二叉树(链式结构)
文章目录 1. 二叉树的性质2. 链式结构二叉树3. 二叉树链式结构的4种遍历方式4. 二叉树节点个数5. 二叉树的叶子节点个数6. 二叉树第k层节点个数7. 二叉树的高度/深度8. 二叉树查找值为x的节点9. 二叉树的销毁10. 判断是否为完全二叉树11. 二叉树练习题11.1 单值二叉树11.2 相同…...
【CSS】居中样式
对于行内元素,使用 text-align: center。对于已知宽度的块级元素,使用 margin: 0 auto。对于需要灵活布局的元素,使用 Flexbox 或 Grid。 flex .parent {display: flex;justify-content: center; /* 水平居中 */align-items: center; /* 垂…...
Vite环境下uniapp Vue 3项目添加和使用环境变量的完整指南
一、引言 在uniapp项目中,合理配置环境变量对于提高开发效率和保障项目安全至关重要。Vite作为新一代的前端构建工具,为环境变量的管理提供了简洁而强大的支持。下面,我们将一步步学习如何在Vite环境下为uniapp Vue 3项目添加和使用环境变量…...
mysql-springboot netty-flink-kafka-spark(paimon)-minio
1、下载spark源码并编译 mkdir -p /home/bigdata && cd /home/bigdata wget https://archive.apache.org/dist/spark/spark-3.4.3/spark-3.4.3.tgz 解压文件 tar -zxf spark-3.4.3.tgz cd spark-3.4.3 wget https://raw.githubusercontent.com/apache/incubator-celeb…...
讨论一个mysql事务问题
最近在阅读一篇关于隔离级别的文章,文章中提到了一种场景,我们下面来分析一下。 文章目录 1、实验环境2、两个实验的语句执行顺序3、关于start transaction和start transaction with consistent snapshot4、实验结果解释4.1、实验14.2、实验24.3、调整实…...
pytest插件精选:提升测试效率与质量
pytest作为Python生态系统中备受推崇的测试框架,以其简洁、灵活和可扩展性赢得了广泛的认可。通过合理使用pytest的各种插件,可以显著提升测试效率、增强测试的可读性和可维护性。 pytest-sugar:提升测试体验 pytest-sugar是一款增强版的py…...
HTB:Sightless[WriteUP]
目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 继续使用nmap对靶机开放的TCP端口进行脚本、服务扫描 首先尝试对靶机FTP服务进行匿名登录 使用curl访问靶机80端口 使用浏览器可以直接访问该域名 使用浏览器直接访问该子域 Getshell 横向移动 查…...
国产化浪潮下,高科技企业如何选择合适的国产ftp软件方案?
高科技企业在数字化转型和创新发展中,数据资产扮演着越来越重要的角色。在研发过程中产生的实验数据、设计文档、测试结果等,专利、商标、版权之类的创新成果等,随着信息量急剧增加和安全威胁的复杂化,传统的FTP软件已经不能满足这…...
自注意力机制
当输入一系列向量,想要考虑其中一个向量与其他向量之间的关系,决定这个向量最后的输出 任意两个向量之间的关系计算 计算其他向量对a1的关联性 多头注意力机制 图像也可以看成一系列的向量,交给自注意力机制处理,CNN是特殊的自注意…...
抽象工厂模式详解
1. 引言 1.1 设计模式概述 设计模式(Design Patterns)是软件开发中解决常见问题的一种最佳实践。它们通过总结经验,提供了一套被验证有效的代码结构和设计原则,帮助开发者提高代码的可维护性、可重用性和可扩展性。 设计模式主…...
【Linux】软硬链接和动静态库
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...
HarmonyOS入门 : 获取网络数据,并渲染到界面上
1. 环境搭建 开发HarmonyOS需要安装DevEco Studio,下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手,比如获取网络数据,并将其渲染到界面上。 本文就是基于…...
【贪心】【哈希】个人练习-Leetcode-1296. Divide Array in Sets of K Consecutive Numbers
题目链接:https://leetcode.cn/problems/divide-array-in-sets-of-k-consecutive-numbers/description/ 题目大意:给出一个数组nums[]和一个数k,求nums[]能否被分成若干个k个元素的连续的子列。 思路:比较简单,贪心就…...
【数据库实验一】数据库及数据库中表的建立实验
目录 实验1 学习RDBMS的使用和创建数据库 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六、实验结果 七、评价分析及心得体会 实验2 定义表和数据库完整性 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
