X86架构(五)——栈操作与寻址操作

news2024/11/15 13:49:15

我们先采用 X86架构(四) 所学知识,在显示器上显示 1+2+3+...+100=

	;代码清单7-1
	;文件名:c07_mbr.asm
	;文件说明:硬盘主引导扇区代码
	;创建日期:2011-4-13 18:02
	
	jmp near __start
	message db '1+2+3+...+100='
__start:
	mov ax, 0x7c0				;数据段基地址
	mov ds, ax
	mov ax, 0xb800				;显存段地址
	mov es, ax
	mov si, message     		;源数据起始地址
	mov di, 0           		;目的地址偏移
	mov cx, start - message		;计算字符数量,并存储在cx
__loop_1:
	mov al, [si]				;获取源地址数据
	mov [es:di], al				;将数据传送到目的地址[es:di]
	inc di						;段偏移加1
	mov byte [es:di], 0x07		;显示属性跟随存储
	inc di						;段偏移加1
	inc si						;下一个字符的地址
	loop __loop_1				;cx不为0,继续执行__loop_1
	;cx寄存器又为计数寄存器,处理器执行loop时,自动计算cx的值
	;以下计算1100的和
	xor ax,ax					;清空ax寄存器,存放结果
    mov cx,1
__loop_2:
	add ax,cx					;ax = ax + cx
	inc cx						;cx + 1
	cmp cx,100
	jle __loop_2				;小于等于时继续执行__loop_2

栈和栈段的初始化

栈(Stack)是一种后进先出(Last In First Out,LIFO)的数据存储结构,数据的存取只能从一端进行,如下图所示。
栈示意图
和代码段、数据段和附加段一样,栈也是一个内存段,叫栈段(Stack Segment),由段寄存器SS指向。栈的操作有两种,分别是压栈(push)和出栈(pop)。压栈和出栈只能在一端进行,所以需要用栈指针寄存器SP (Stack Pointer)来指示下一个数据应当压入栈内的位置,或者数据从哪里出栈。
定义栈需要两个连续的步骤,即初始化段寄存器SS和栈指针SP的内容。

	;以下计算累加和的每个数位 
	xor cx,cx		;cx清零
	mov ss,cx		;设置ss寄存器
	mov sp,cx		;设置sp寄存器,堆栈段从高地址向低地址生长

	mov bx,10		;除数
	xor cx,cx
__loop_3:
	inc cx			;压栈中用cx记录一共压入栈元素个数,以便之后出栈时能及时停止pop
	xor dx,dx		;dx清零,寄存器ax中保存着被除数,32位被除数[dx:ax]
	div bx			;除数bx
	or dl,0x30		;余数在dx中,但是余数最多到9,因此在dl中就够了,加0x30得到ASCII码
	push dx			;dx中只有dl有意义,但是压栈的单位必须是字(两个字节)
	cmp ax,0
	jne __loop_3	;ax不为0跳转,商为0时,不需要再除

NOTE
8086 处理器压栈时只能压入一个字
处理器在执行push指令时,首先将栈指针寄存器SP的内容减去操作数的字长(以字节为单位的长度,在16位处理器上是2),然后,把要压入栈的数据存放到逻辑地址SS:SP 所指向的内存位置(和其他段的读写一样,把栈段寄存器SS 的内容左移4 位,加上栈指针寄存器SP 提供的偏移地址)。如下图所示,当push指令第一次执行时,SP的内容减2,即0x0000-0x0002=0xFFFE,借位被忽略。于是,被压入栈的数据,在内存中的位置实际上是0x0000:0xFFFE。push指令的操作数是字,而且Intel 处理器是使用低端字节序的,故低字节在低地址部分,高字节在高地址部分,正好占据了栈段的最高两个字节位置。
段分配
NOTE
不同于代码段,代码段在处理器上执行时,是由低地址端向高地址端推进的,而压栈操作则正好相反,是从高地址端向低地址端推进的。
压栈状态
经过上方的各个程序,1~100的累加和被分解并存储到栈中,下面我们将位数从栈中取出并显示到显示器上

__loop_4:
	pop dx			;出栈,栈顶元素是千位,百位,十位,个位
	mov [es:di], dl ;dl保存低位,位数不超过10
	inc di			;偏移地址加1
	mov byte [es:di],0x07	;显示属性
	inc di					;__loop_4
	loop __loop_4	;cx在上段程序中已经完成赋值

	jmp near $ 		;死循环

NOTE

  • push 指令的操作数可以是16位寄存器或者16位内存单元
  • 栈在本质上也只是普通的内存区域,只是使用push和pop指令来访问比较方便
  • 要注意保持栈平衡
  • 在编写程序前,必须充分估计所需要的栈空间,以防止破坏有用的数据

8086处理器的寻址方式

1. 寄存器寻址
指令的操作数位于寄存器中,如

mov ax, cx
add bx, 0xf000
inc dx

2. 立即寻址
立即寻址也叫立即数寻址,指令的操作数是一个立即数

add bx, 0xf000  ;操作数0xf000为立即数
mov dx, label_a ;操作label_a是一个标号,也是立即数

3. 内存寻址
8086处理器访问内存时,采用的是段地址左移4位,然后加上偏移地址,来形成20位物理地址的模式,段地址由4 个段寄存器之一来提供,偏移地址要由指令来提供。所以内存寻址就是如何在指令中提供偏移地址,供处理器访问内存时使用。
3.1 直接寻址
使用该寻址方式的操作数是一个偏移地址,而且给出了该偏移地址的具体数值。

mov ax, [0x5c0f] 			;逻辑地址[DS:0x5c0f]
add word [0x0230], 0x5000 	;逻辑地址[DS:0x0230]
xor byte [es:label_b], 0x05	;ES为段超越前缀

3.2 基址寻址
基址寻址,就是在指令的地址部分使用基址寄存器BX或者BP来提供偏移地址。

;DS的内容左移4位,加上基址寄存器BX中的内容,形成20位的物理地址。
mov [bx], dx		;逻辑地址[DS:bx],
add byte [bx], 0x55	;逻辑地址[DS:bx]

使用基址寻址可以使代码边的更简洁高效,如

buffer:
	dw 0x20, 0x100, 0x0f, 0x300, 0xff00

	mov bx, buffer	;数据的偏移地址
	mov cx, 4
__loop:
	inc word [bx]
	add bx, 2		;字操作,所以加2
	loop __loop

BP用作基址寻址的寄存器时,在形成20位的物理地址时,默认的段寄存器是SS。所以,它经常用于访问栈。

;处理器将栈段寄存器SS的内容左移4位,加上寄存器BP的内容,形成20位的物理地址,
;然后将该地址处的一个字传送到寄存器AX中。
mov ax, [bp]

同时,利用此方式可以访问栈中的内容而不破坏栈的状态,尤其是SP寄存器中的内容。

mov ax, 0x5000
push ax
mov bp, sp		;保存sp的内容
mov ax, 0x7000
push ax
mov dx, [bp]	;访问前面保存的SP对应的栈中的内容

3.3 变址寻址
变址寻址类似于基址寻址,但变址寻址使用的是变址寄存器(或称索引寄存器)SI和DI。例如:

;默认使用段寄存器DS指向的数据段,偏移地址由寄存器SI或者DI提供
mov [si], dx
add ax, [di]
xor word [si], 0x8000
;使用段超越前缀
add bx, [es:si]

3.4 基址变址寻址
使用基址变址的操作数可以使用一个基址寄存器(BX 或者BP),外加一个变址寄存器(SI 或者DI)。

;肯定也是默认使用DS指向的数据段啦
mov ax, [bx+si]
add word [bx+di], 0x3000

哈哈哈哈哈,下面就要开始学习更多内容啦
让我们一起进步吧 Bro

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

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

相关文章

APP封装安装配置参考说明

APP封装安装配置参考说明 一, 环境准备 宝塔环境 nginx php5.6 mysql5.6 java-openjdk1.8 apktool 1,安装 nginx,php,mysql自行安装 java-openjdk1.8 安装 推荐使用命令行安装 1.1 yum install java-1.8.0-openjdk1.2 yum install -y java-1.8.0-openjdk-devel1.3 设置…

Intellij Idea + Git 完美实战!

环境准备 使用前需要安装一个远程的 Git 仓库和本地的 Git 客户端。由于IDEA中的Git插件需要依赖本地Git客户端,所以需要进行如下配置: 如果本地已有项目,直接通过如下操作,即可在远程自动创建仓库并关联 1. 克隆远程仓库代码&am…

halcon4

图像采集助手-Image Aequisition 1.配置相机IP 和巨型帧等 2.通过海康MVS软件 找到 对应halcon 版本 3. 找到对应halcon版本的 海康相机文件 4.找到Halocn文件目录 粘贴上图文件 通过halcon 助手 -Image Aequisition -自动检测 -找到MVision接口 连接相机 采集图像 实时…

一句话概括TMMi的每个PA

TMMi(Test Maturity Model Integration,测试成熟度模型集成)是一个由TMMi基金会开发的非商业化的测试成熟度模型,是对CMMI模型的一个补充。它可以帮助组织使测试过程从未管理的状态进化为已管理、已定义、已测量和优化的状态。 T…

网站建设完成后,视频类网站如何做seo

视频类网站的SEO优化是一个综合性的工作,涉及从内容优化、技术优化到外部链接建设等多个方面。由于视频类网站主要提供的是视频内容,其SEO优化不仅需要关注常规的网页优化技巧,还需要考虑视频特有的元素和用户行为模式。以下是针对视频类网站…

Xilinx高速接口之GTP

简介 开坑计划中,主要参考ug482 主要讲解结构以及原语 以及时钟路由和一些其他的 GTP_COMMON还好,需要设置的不多,原语也短, GTP_CHANNEL需要设置的东西真多,原语也长 还好有官方参考例程以及自动生成的原语例化 不然…

0基础学习Python路径(31)logging模块

Python logging 模块定义了为应用程序和库实现灵活的事件日志记录的函数和类。 程序开发过程中,很多程序都有记录日志的需求,并且日志包含的信息有正常的程序访问日志还可能有错误、警告等信息输出,Python 的 logging 模块提供了标准的日志接…

OpenCV绘图函数(4)绘制轮廓线的函数drawContours()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 函数会在图像中绘制轮廓线&#xff0c;如果 thickness ≥ 0&#xff0c;则绘制轮廓线&#xff1b;如果 thickness < 0&#xff0c;则填充由轮…

【JLINK】RTT Viewer 的使用

​​​​​​ 一、使用说明 1.1 查找 RTT 缓冲区的开始位置 echo off if exist .\Debug\%PRJ_NAME%.map (findstr /C:" _SEGGER_RTT" .\Debug\%PRJ_NAME%.map rem findstr /C:" __StackTop " .\Debug\%PRJ_NAME%.map rem findstr /C:" Reset_Handle…

从欧拉公式的美到旋转位置编码RoPE

也许你在某些场合听说过欧拉公式&#xff0c;也许你干脆对数学不感冒。机缘巧合下&#xff0c;你点开了这篇文章&#xff0c;大致浏览了下然后关闭&#xff0c;继续为自己的工作学习忙碌。这不妨碍你暂停忙碌的脚步&#xff0c;欣赏她的美。 若干年后&#xff0c;你应该不曾记得…

Java基础(2)- Java环境

目录 一、jvm和跨平台 二、JDK 和 JRE 三、JDK的下载和安装 四、配置环境变量 一、jvm和跨平台 1.jvm&#xff08;Java虚拟机&#xff09;类似于翻译官&#xff1a;java运行程序的假想计算机&#xff0c;主要运行java程序。 2.跨平台&#xff1a;指不同操作系统。 3.关系…

网上买大流量卡要问哪些问题?几个常见的问与答!

大家都比较关注的几个常见的流量卡问题&#xff0c;答案来喽&#xff01; 这几个问题特别适合刚刚接触流量卡的朋友&#xff0c;如果你在购买流量卡时不知道该了解什么&#xff0c;该向商家问什么的时候&#xff0c;不妨问问这几个问题吧&#xff0c;接下来&#xff0c;这篇文…

python 实现square root平方根算法

square root平方根算法介绍 计算平方根&#xff08;Square Root&#xff09;的算法有多种&#xff0c;这里介绍几种常见的方法&#xff1a; 牛顿迭代法&#xff08;Newton’s Method&#xff09; 牛顿迭代法是一种在实数域和复数域上近似求解方程的方法。对于平方根问题&…

home kit认证

在当今快节奏的生活中&#xff0c;智能家居技术正不断改变我们的居住体验。home kit 将这一领域提升到了全新的高度。它不仅让智能家居设备的管理变得更为简单直观&#xff0c;还通过高水平的安全性和互操作性&#xff0c;为用户提供了无缝的体验。 一、什么是home kit home k…

CentOS7将yum源更换为国内源保姆级教程

在 CentOS 7 系统中更改 YUM 源到国内源可以显著提高软件包的下载速度&#xff0c;因为国内源服务器通常距离中国大陆用户更近。以下是一个详细的步骤来完成这一操作&#xff1a; 步骤 1: 备份原有配置 首先&#xff0c;备份原系统中的 yum 配置文件以防万一&#xff1a; BA…

红黑树模拟实现STL中的map与set——C++

1.红黑树的迭代器 &#xff08;本篇代码基于我写的红黑树的实现这篇博客&#xff09; 迭代器的好处是可以方便遍历&#xff0c;是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代器&#xff0c;需要考虑以下问题&#xff1a; begin()与end()&#xff1a; STL明确规定&…

无人机侦测:光电识别追踪设备(双光)技术详解

无人机侦测中的光电识别追踪设备&#xff08;双光&#xff09;技术&#xff0c;是一种高效且精准的目标识别与追踪手段&#xff0c;特别适用于无人机平台。以下是对该技术的详细解析&#xff1a; 一、技术概述 光电识别追踪设备&#xff08;双光&#xff09;结合了可见光和红…

企业微信iPad协议:自定义接入需求,为行业提供新助力

在当今数字化时代&#xff0c;企业如何有效连接客户、提升营销效率成为了一个重要议题。iPad协议&#xff0c;或称企业微信协议&#xff0c;作为基于微信iPad协议的智能接口服务&#xff0c;优势及其在企业营销中的应用。 什么是iPad协议&#xff1f; iPad协议是一种智能控制…

<数据集>塑料瓶识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3331张 标注数量(xml文件个数)&#xff1a;3331 标注数量(txt文件个数)&#xff1a;3331 标注类别数&#xff1a;1 标注类别名称&#xff1a;[bottle] 使用标注工具&#xff1a;labelImg 标注规则&#xff1a;对…

Swift concurrency 2 — async await的理解与使用

async / await 将函数标记为async会告诉Swift编译器该函数是异步执行的&#xff0c;是可以挂起的。await关键字标记了这些挂起点。当一个函数在await调用时被挂起时&#xff0c;它所执行的线程可以用来执行其他工作。当等待的工作完成时&#xff0c;运行时可以恢复函数的执行。…