[从零学习汇编语言] - BX寄存器与loop指令

2023-11-16

前言

点赞再看,养成习惯!

该系列博文基于王爽老师 <汇编语言 第四版> 一书,需要的同学链接自取:

链接:https://pan.baidu.com/s/1NAgD1Z15LtK1BuH92xmICA
提取码:xlzb

另外书中提到的DosBox软件不想去官网下载的小伙伴也可以自取:

链接:https://pan.baidu.com/s/1O6PnLb_hN-WUS2avicNpcw
提取码:xlzb

最后如果还没有计算机基础的同学,建议先补充下计算机相关的基础知识:

笔记目录总览

今天我们的学习目的是加深BX寄存器的了解以及学习一个新的重要指令:loop。今天的内容虽然非常简单,但是还是需要大家多多练习,增加熟练度。

一、 Bx寄存器与[偏移地址]

之前我们有讲过CPU寻址是通过段地址:偏移地址实现的,比如:
在这里插入图片描述
上图中2000:0010中的2000便是段地址,0010便是偏移地址,而再进一步,我们还可以通过DS段地址寄存器来替代段地址:
在这里插入图片描述
再之后,我们还是觉得这种方式不够灵活,于是我们又引入了[偏移地址]的方式来表示物理地址,当我们使用这种方式的时候,CPU会默认的取DS寄存器的值作为段地址:

在这里插入图片描述
但是随着我们学习的深入,我们发现单纯的通过[偏移地址]的形式已经无法满足我们的需求了,这种方式无法动态的去将一个变化的值赋与指令中,为了解决这个问题,我们需要引入一个新的寄存器来保存偏移地址的数据。之前我们有提到过四个通用寄存器:AX,BX,CX,DX。当时我们只是简单的提到过它们是四个通用数据寄存器,并没有详细的去讲他们的具体作用,今天我们就要用到它们中的BX寄存器。

让我们来整理下已经明确过用途的寄存器
1. 用来记录指令执行信息的
cs: 指令段地址寄存器
ip: 指令偏移地址寄存器
2. 用来记录栈信息的
ss: 栈段地址信息寄存器
sp:栈偏移地址寄存器
3. 用来存放数据信息的
ds: 数据段地址寄存器

今天要讲的BX寄存器 又叫做基地址寄存器(Base Register),通常被我们用来存放需要用到的存储器地址。它的用法很简单,只需要通过[BX]的格式即可表示取bx寄存器中数据的值作为偏移地址:
在这里插入图片描述

这里为基础不好的同学解释下上面都做了什么哈
1. 修改ds和bx寄存器的值
2. 修改ds:bx寄存器对应的存储空间的值
3. 将[bx]地址的值赋予ax寄存器,观察效果
4. 将bx寄存器的值赋予ax寄存器,观察效果

这里我们可以很明显的观察到,[bx]的表达形式与[ADRESS]相似,都是获取ds寄存器作为段地址,自身作为偏移地址的方式来表达物理地址。

二、 loop指令与jmp指令

1. jmp指令

loop指令是我们今天要新学的汇编指令,在学习前我们先整理下我们已经讲过的指令有哪些:

1. mov 赋值指令
2. add 加法运算
3. sup 减法运算
4. push 入栈
5. pop 出栈

再讲loop指令之前,我们需要先学习一下另一个汇编指令:jmp 。jmp指令是汇编语言中的无条件跳转命令,可以跳转到内存中任何程序段,偏移地址可在指令中给出,也可以在寄存器中给出,或者再存储器中给出。为了方便大家理解,我们还是提出一个小题目来讲解。

还记得我们只前举例说的求2的三次幂吗?让我们再来实现一次
只不过这次我们需要用编写源程序的形式来实现。
我们先来声明一个数据段:
codesg segment
...
codesg ends

然后接下来我们来实现下数据段的逻辑
codesg segment 
mov ax,2H
add ax,ax
add ax,ax

mov ax,4c00H
int 21H
codesg ends 

然后让我们声明下数据段并设置终止点
assume cs:codesg
codesg segment 
mov ax,2H
add ax,ax
add ax,ax

mov ax,4c00H
int 21H
codesg ends 
end

我们来运行下:
在这里插入图片描述
注意点

  1. 我创建的源文件名称为codea,因此我在编译,连接阶段输入的指令为 masm codea 及 link codea ,如果不了解连接编译概念的请查看上一篇笔记:
    [从零学习汇编语言] - 源程序与EXE文件
  2. debug追踪一直到mov ax,4c00H 指令就为止了,
    mov ax,4c00H
    int 21H

    这两个指令为返回指令,暂时不讲,了解即可。

结果
通过三次加法模拟乘法运算,我们已经可以成功的求解出2的三次方的值,但是此时我们也发现这种实现方式存在一些弊端,如果我们想要求解2的10次方,岂不是要讲上述代码赋值10次?同理如果是100次幂,1000次幂呢?那我们该如何优化呢?这里就要用到刚刚要讲的jmp指令了。

 使用前我们先介绍下jmp指令支持的格式:
 1. jmp 段地址
 2. jmp 寄存器
 3. jmp 段地址:偏移地址
 4. jmp 标号


让我们来改造下上面的程序:

assume cs:codesg
codesg segment 
mov ax,2H
multi: add ax,ax
jmp multi    ; 这里multi为上面设置的标号
 
mov ax,4c00H
int 21H
codesg ends 
end

试一下运行结果:
在这里插入图片描述
这里可以观察到,我们已经可以没有次数限制的进入mov ax,ax代码段,无论我们想要获取2的多少次幂都可以了。但是这里还有一个问题,由于jmp指令是一个无条件跳转指令,在我们这个代码段中,它只会无限制的重复上述指令段,无法退出,那么我们有没有什么办法进行优化呢?

2. loop指令

loop指令是一种有条件的跳转指令,它需要在跳转前判断CX寄存器中的值,如果CX不为零则跳转至标号继续执行指令,为0则继续向下执行指令。

当cpu执行到loop指令的时候会进行两步操作:
1. cx =cx-1
2. 判断cx是否为零

loop指令支持的格式很简单
loop 标号 即可

而我们可以通过loop判断cx值的特性来实现有限制的跳转循环,接下来让我们改造下代码:

assume cs:codesg
codesg segment 
mov ax,2H
mov cx,3H
multi: add ax,ax
loop multi    ; 这里multi为上面设置的标号
 
mov ax,4c00H
int 21H
codesg ends 
end

观察下结果(这里省下编译连接的操作,小伙伴不要忘了):
在这里插入图片描述
注意
我们已经观察到LOOP指令已经可以按照我们赋予cx寄存器的值3作为判断跳出循环,但是有的小伙伴会对运算结果有一些疑问:

在这里插入图片描述
这里会有小伙伴疑惑2的三次幂不应该是16吗,为什么这里会显示10?还记得我们说过DosBox的数值显示默认是十六进制的吗?那么十六进制的16对应的表示方法就是10,不信的小伙伴可以用windows自带的程序员计算器验证:

在这里插入图片描述

三、 一些奇奇怪怪的注意点

1. 汇编源程序的数字问题

讲到这里我们还要讲一个规则:在汇编源程序中,数据不能以字母开头。

比如:
我们不能够这样赋值: mov ax,ffffh
而是需要
mov ax,0ffffh

这里的0是为了防止以字母开头,而h则是表示当前数字为十六进制数

2. Debug和Masm的区别

(1) mov ax,[0] 问题

还记得我们之前在Debug的使用中讲过mov ax,[0]中的[0] 可以表示偏移地址吗?但是在Masm中并不支持这种写法,它会将这个指令直接编译为mov ax,0 。这个时候就需要我们将偏移地址放入bx寄存器中,通过 [bx] 的形式表达。我们也可以参考《汇编指令第四版》中的方法:
在这里插入图片描述

3. 段前缀

我们之前说过可以通过mov ax,[bx] 的方式获取物理地址对应的存储单元的值,其中偏移地址由bx寄存器给出而段地址则默认为bs寄存器给出。当然我们也可以显式的更改段寄存器,比如mov ax,cs:[bx] 。折现出现在访问内存单元指令中,用于显式的指明内存单元的段地址,在汇编语言中被称为段前缀

四、课后作业

1. 题目

在这里插入图片描述

2. 答案

问题一

assume cs:codesg
codesg segment 

mov ax,0000H
mov ds,ax
mov bx,200H
mov al,00H
mov cx,3FH

flagA:  mov ds:[bx],ax
		add ax,1H
		add bx,1H
		loop flagA
mov ax,4c00H
int 21H
codesg ends 
end

问题二

assume cs:codesg
codesg segment 
mov ax,20h
mov ds,ax
mov bx,00h
mov cx,3fh
flagA : mov ds:[bx],bx
        add bx,1h
		loop flagA
mov ax,4c00H
int 21H
codesg ends 
end

结语

今天的内容就到此结束了,有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
屏幕前努力学习的你如果想要持续了解博主最新的学习笔记或收集到的资源,可以关注博主的个人公众号。这里有很多最新的技术领域PDF电子书及好用的软件分享在这里插入图片描述

码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
如果大家有什么意见和建议请评论区留言或私聊博主,博主会第一时间反馈的哦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[从零学习汇编语言] - BX寄存器与loop指令 的相关文章

  • 如何为Python 3子进程分配CPU亲和力?

    我在 Python 方面还是个新手 我在 Windows 7 和 Windows 10 上运行 Tkinter GUI 我有一个子进程以 1 KHz 运行数据记录器例程 我想为子进程设置 cpu 亲和力 我正在使用 Python 3 8 进
  • 用标签数据填充 x86_64 指针前十六位?

    由于当前的 x86 64 实现仅能够使用 48 位 虚拟 地址空间来降低 MMU 复杂性 因此前 16 位是否可用于实现安全标签数据 当前的实现是否限制这种使用 即使知道IP和其他段寄存器是完整的六十四位 并将指针的前十六位限制为仅包含虚拟
  • 线程(在 Java 或 C++ 程序中)与 CPU 核心数之间有什么关系?

    有人可以解释一下吗 i7 处理器可以运行 8 个线程 但我很确定我们可以在 JAVA 或 C 程序中创建超过 8 个线程 但不确定 我有一个 i5 处理器 在研究并发性时我创建了 10 个线程用于分配 我只是想了解 CPU 的核心评级与线程
  • 世微AP9196 DC-DC 升压恒流电源管理芯 电解水驱动电源应用线路

    AP9196 是一系列外围电路简洁的宽调光比升压调光恒流驱动器 适用于 3 40V 输入电压范围的 LED照明领域 AP9196 采用我司专利算法 可以实现高精度的恒流效果 输出电流恒流精度 3 电压工作范围为5 40V 可以轻松满足锂电池
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • DOSBox 上的 8086 程序集: idiv 指令有错误?

    我正在帮助我的一个朋友调试他的程序 我们将其范围缩小到甚至在这里出现的问题 MODEL small STACK 16 CODE start mov ax 044c0h mov bl 85 idiv bl exit mov ax 4c00h
  • 您的CPU不支持VT-x

    我已经创建了 AVD 但是当我尝试运行 android 程序时 它显示 错误 您的CPU不支持VT x 我在 BIOS 中启用了虚拟化技术 但当我尝试运行 Android 程序时仍然出现此错误 有两种情况 使用VMware 进入 WM gt
  • 如何在Python中模拟CPU和内存压力

    我想知道是否有人用 python 编写了模拟 cpu 和内存压力的代码 我看到一段加载 cpu 的代码 但如何强制它们在 90 的使用率下工作 一个节点主要有 4 种经常使用的资源 有效内存 中央处理器周期 储存空间 网络负载 上传和下载
  • OpenACC 是否会影响正常的 GPU 渲染?

    我试图弄清楚是否可以使用 OpenACC 代替正常的 CPU 串行执行调用 通常我的编程都是关于 3D 编程 或者以某种方式正常使用 GPU IE 图像处理或其他需要使用着色器的渲染类型 我想弄清楚这个图书馆是否对我有利 我问这个问题的原因
  • Tensorflow 相同的代码,但从 CPU 设备到 GPU 设备得到不同的结果

    我正在尝试实现一个程序来测试 GPU 设备上的 Tensorflow 性能 数据测试是MNIST数据 使用多层感知器 神经网络 进行监督训练 我跟着这个简单的例子 http gist github com nishidy 8176548ec
  • 尝试了解 asm 中断,特别是 16h func 01H

    这是家庭作业 我不期望你解决我的问题 只需要一些理解 我必须在 dosbox 中使用 ASM 和 C 我的第一个问题是我不太明白如何使用 BIOS 中断 任何带有代码示例的好的教程都会非常感激 好吧 我知道有中断 每个中断都有自己的功能和参
  • 单核上的多线程有什么意义?

    我最近一直在研究 Linux 内核 并回顾了大学操作系统课程的时代 就像那时一样 我正在玩线程之类的东西 一直以来我一直假设线程是自动在多个核心上同时运行但我最近发现您实际上必须显式编写代码来处理多个核心 那么单核上的多线程有什么意义呢 我
  • 为什么每个逻辑 CPU 在多线程情况下都有自己的 CR3 寄存器?

    当我们有一个支持某种形式的多线程的 CPU 时 每个逻辑 CPU 都有它自己的一组寄存器 至少 包括 CR3 寄存器 由于我们在执行不同线程时正在处理同一进程的虚拟地址空间 并且永远不会发生上下文切换 切换同一进程的线程时TLB缓存也不会失
  • CPU如何对指令重新排序

    我最近读到了有关 CPU 指令重新排序以提高效率的内容 但我无法理解CPU如何重新排序其指令 我的意思是编译时重新排序是可以想象的 因为编译器可以预见即将到来的代码 但是对于一个接一个地读取指令的CPU 它如何看到即将到来的指令并对它们重新
  • 使用 AMD FX 4100 四核获取 Linux ubuntu 12.10 上的 CPU 温度

    有很多类似的问题 但我还没有找到解决方案 如何在 Linux Ubuntu 12 10 上使用 C 或 C 获取 CPU 温度无需致电 sensors 我当然可以从文件中读取它 但是我找不到它在 12 10 中的存储位置 简单地读取文本文件
  • 当JVM执行Java应用程序时,操作系统的作用是什么?为什么我们需要操作系统?

    我在网上读过一些资料 有人说Java应用程序是由java虚拟机 JVM 执行的 执行 这个词让我有点困惑 据我所知 非Java应用程序 即 用C C 编写 可以由操作系统执行 在较低级别 这意味着操作系统将二进制程序加载到内存中 然后指示C
  • Xcode 9 - CPU 使用率高 - 风扇最大速度

    自从我升级到 Xcode 9 后 当我在 Xcode 上工作时 我的粉丝就变得疯狂了 当我使用 Storyboards 和 Interface Builder 时 尤其会发生这种情况 Xcode有时会占用100 的CPU 并且名为 Inte
  • C# 程序占用太多CPU?

    我有一个程序 它在启动时不断地在 3 个独立的计时器之间切换 我的应用程序的主线程有一个 while 循环 它不断检查全局变量是否已设置为 true 如果设置为 true 它将停止一个计时器并启动另外两个计时器 一个连续 另一个自动停止 如
  • 我试图在 AAM 指令之后使用 AX 中存储的值将其除以 2,为什么它不适用于 2 位数字输出?

    英语不是我的母语 请原谅输入错误 我将在此处显示的代码是一项作业 我真的需要了解发生了什么事 我在 DosBox 0 74 和 TASM 汇编器中使用 Intel 8086 语法 当我必须除以 2 时 代码的问题在于三角形的面积 注意 程序
  • CPU是如何做减法的?

    我有一些基本的疑问 但每次我坐下来尝试面试问题时 这些问题和我的疑问就会出现 假设 A 5 B 2 假设A和B都是4字节 那么CPU是怎么做的呢 A B添加 我知道 A 的符号位 MSB 为 0 表示正值 B 的符号位为 1 表示负整数 现

随机推荐

  • 简易的打包器--webpack打包原理

    手写一个简单的类似webpack的打包器 打包流程说明 定义依赖分析函数 通过读取文件内容 分析得到该文件导入的依赖项 code gt AST gt 得到导入声明 记录导入声明中的依赖项路径 gt AST gt code gt 返回记录当前
  • 扫描局域网内所有电脑的端口

    扫描局域网内所有电脑端口可以使用工具如Nmap来完成 Nmap是一个开源的网络探测工具 可以用来扫描端口 识别操作系统 检测服务和插件等 使用Nmap扫描局域网内所有电脑端口的命令如下 nmap sP 192 168 1 0 24 其中19
  • kvm直通sata_PVE 中 对 KVM虚拟机的USB设备设置为直通

    Proxmox支持将USB设备直接映射给KVM虚拟机使用 也就是所谓的USB Passthrough 配置步骤可以参考Proxmox wiki上的有关说明 具体地址是https pve proxmox com wiki USB physic
  • Java随机数

    1 指定数字范围 package com jiayou peis official account biz utils import java util Random public class Test public static void
  • Python模拟登陆万能法-微博

    Python模拟登陆让不少人伤透脑筋 今天奉上一种万能登陆方法 你无须精通HTML 甚至也无须精通Python 但却能让你成功的进行模拟登陆 本文讲的是登陆所有网站的一种方法 并不局限于微博与知乎 仅用其作为例子来讲解 用到的库有 sele
  • ubuntu使用教程与常用命令

    ubuntu使用教程 一 Ubuntu简介 Ubuntu 乌班图 是一个基于Debian的以桌面应用为主的Linux操作系统 据说其名称来自非洲南部祖鲁语或科萨语的 ubuntu 一词 意思是 人性 我的存在是因为大家的存在 是非洲传统的一
  • pdf.js详细解析

    pdf js可以实现在html下直接浏览pdf文档 是一款开源的pdf文档读取解析插件 pdf js主要包含两个库文件 一个pdf js和一个pdf worker js 一个负责API解析 一个负责核心解析 pdf js可通过pdf文件的地
  • 神奇的tmux

    一 Tmux 是什么 1 1 会话与进程 命令行的典型使用方式是 打开一个终端窗口 terminal window 以下简称 窗口 在里面输入命令 用户与计算机的这种临时的交互 称为一次 会话 session 会话的一个重要特点是 窗口与其
  • STM32+4G模块实战项目(连接阿里云物联网平台+OTA升级):(一)初识硬件

    STM32 4G模块实战项目 OTA升级 构思占坑中ing 3天一章 请耐心等待 STM32 4G模块实战项目 连接阿里云物联网平台 OTA升级 一 初识硬件 STM32 4G模块实战项目 连接阿里云物联网平台 OTA升级 二 stm32通
  • @RefreshScope刷新配置文件原理

    一 前置知识 在Spring中bean的作用域 scope 常用的有两种 单例 singleton 原型 prototype Bean的Scope影响了Bean的管理方式 例如创建Scope singleton的Bean时 IOC会将这些B
  • android Http通信(访问web server)

    下面将3种实现方式 以下代码有的来源于传智播客 有的自己琢磨的 在这感谢传智播客 本人开发使用的android studio 在最新版本中 android不在支持HttpClient 所以 要使用HttpClient要加载库文件 1 com
  • 单向散列函数(Hash)

    0 Hash函数的性质 常用Hash函数 MD5 128bit SHA 1 160bit 等 1 使用Hash 函数进行完整性验证的模型 2 使用Hash函数进行口令验证 1 3 使用Hash函数进行口令验证 2 4 使用Hash解决数字签
  • 剑指offer(简单)

    目录 数组中重复的数字 替换空格 从尾到头打印链表 用两个栈实现队列 斐波那契数列 青蛙跳台阶问题 旋转数组的最小数字 二进制中的1的个数 打印从1到最大的n位数 删除链表的节点 调整数组顺序使奇数位于偶数前面 链表中倒数第k个节点 反转链
  • 史上最详细的maven仓库详解

    写在前面 我是 沸羊羊 昵称来自于姓名的缩写 fyy 之前呕心沥血经营的博客因手残意外注销 现经营此账号 本人是个小菜 正向着全栈工程师的方向努力着 文章可能并不高产 也很基础 但每写一篇都在用心总结 请大佬勿喷 如果您对编程有兴趣 请关注
  • 新增、修改入参方法

    一 HttpServletRequest req 获取参数值value 1 Postman 在params逐个参数赋值 PostMapping xxx String id req getParameter id 后端通过如上的方法一个个去获
  • 一文全览各种ES查询在Java中的实现

    点击关注公众号 互联网架构师 后台回复 2T获取2TB学习资源 上一篇 Alibaba开源内网高并发编程手册 pdf ElasticSearch多种查询操作 前言 词条查询 等值查询 term 多值查询 terms 范围查询 range 前
  • Dubbo+Zookeeper+Spring mvc+Nginx 集群负载均衡 详细demo

    原文链接 https blog csdn net xianghui12333 article details 71172342 处女博客 不知道规则怎么写 直接入主题吧 很多人刚接触分布式 集群负载均衡时都觉得高深莫测 难度有点大 其实起码
  • 让你的手机号码变成空号!没试过

    输入 21 13800000000 再按拨号键 注意13800000000这是个空号 原理就是 21 是无条件转移所有来电 13800000000是个空号 如果13800000000的号不起作用你就随便输入个号码什么的 自然别人打进来您的号
  • r730xd服务器重装系统后风扇声音大,重装Win10系统后散热风扇噪音特别大的处理方法...

    有的小伙伴为了解决一些问题 便给电脑重装系统了win10系统 但是在重装后 却又出现了新的问题 在重装完win10后散热风扇噪音响声特别大 非常影响电脑的使用心情 那么遇到这种情况应该怎么办呢 下面小编就给大家分享一下重装Win10系统后散
  • [从零学习汇编语言] - BX寄存器与loop指令

    文章目录 前言 一 Bx寄存器与 偏移地址 二 loop指令与jmp指令 1 jmp指令 2 loop指令 三 一些奇奇怪怪的注意点 1 汇编源程序的数字问题 2 Debug和Masm的区别 1 mov ax 0 问题 3 段前缀 四 课后