【汇编语言】汇编语言程序

【汇编语言】汇编语言程序


文章目录

  • 【汇编语言】汇编语言程序
  • 前言
  • 一、用汇编语言写的源程序
    • 汇编语言编写程序的工作过程
    • 程序中的三种伪指令
    • 源程序编译链接后变为机器码
    • 汇编程序的结构
    • 如何写出一个程序来
    • 程序中可能的错误
  • 二、由源程序到程序运行
    • 由源程序到执行可执行文件的过程
    • 编译
    • 提示语法错误
    • 连接
    • 执行可执行程序
    • 小结
  • 三、运行及跟踪
    • Debug装载程序
    • 用Debug 单步执行
    • P命令和G命令
    • 执行的不同方式
    • 在这里插入图片描述
  • 四、[……]和(……)
    • [……]与(……)的约定
    • 符号idata表示常量
  • 五、Loop指令
    • 用Loop指令编程实例
    • t命令和p命令的区别
    • 循环是否越界
  • 六、段前缀的使用
    • 引入段前缀:一个“异常”现象及对策
    • 访问连续内存单元---loop和[bx]联手
    • 段前缀的使用
  • 七、在代码段中使用数据
    • 应用案例
  • 八、在代码段中使用栈
    • 在代码段中使用栈:以数据逆序存放为例
    • 数据逆序存放程序
  • 九、将数据、代码、栈放入不同段
  • 总结


前言

本篇文章将详细讲到用汇编语言写的源程序,由源程序到程序运行的过程,用Debug跟踪程序的执行,[……]和(……)的区别,Loop指令的详细介绍和使用,段前缀的使用,如何在代码段中使用数据,在代码段中使用栈以及将数据,代码,栈放入不同段。


一、用汇编语言写的源程序

汇编语言编写程序的工作过程

汇编程序:包含汇编指令伪指令的文本。

assume cs:codesg
codesg segment
mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax
mov ax,4c00h
int 21h
codesg ends
end
在这里插入图片描述

程序中的三种伪指令

在这里插入图片描述

源程序编译链接后变为机器码

在这里插入图片描述

汇编程序的结构

  • Debug中直接写入指令编写的汇编程序:
    1、适用于功能简单、短小精悍的程序
    2、只需要包含汇编指令即可
  • 单独编写成源文件后再编译为可执行文件的程序:
    1、适用于编写大程序
    2、需要包括汇编指令,还要有指导编译器工作的伪指令
    3、源程序由一些段构成,这些段存放代码、数据,或将某个段当作栈空间
  • ; —注释

assume cs:code,ds:data,ss:stack
data segment
dw 0123H,0456H,0789H,0abcH,0defH
data ends
stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends
code segment
mov ax,stack
mov ss,ax
mov sp,20h ;设置栈段
mov ax,data
mov ds,ax ;设置数据段
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s

code ends
end

代码段不用设置。

如何写出一个程序来

例:编程求2^3。
1、定义一个段
2、实现处理任务
3、指出程序在何处结束
4、段与段寄存器关联
5、加上程序返回代码

1、
abc segment
abc ends

2、
abc segment

mov ax,2
add ax,ax
add ax,ax

abc ends

3、
abc segment

mov ax,2
add ax,ax
add ax,ax

abc ends

end

4、

assume cs:abc

abc segment

mov ax,2
add ax,ax
add ax,ax

abc ends

end

5、

assume cs:abc

abc segment

mov ax,2
add ax,ax
add ax,ax

mov ax 4c00h
int 21h

abc ends

end

程序中可能的错误

  • 语法错误
    程序在编译时被编译器发现的错误;
    容易发现下面程序中错误

aume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,sx
end
1.assume写错2.没有段结束3.没有程序结束

  • 逻辑错误
    程序在编译时不能表现出来的、在运行时发生的错误;
    不容易发现下面程序中的错误

求2^3
assume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,bx ;寄存器写错
mov ax,4c10H;结束应为4c00h
int 21H
abc ends
end


二、由源程序到程序运行

由源程序到执行可执行文件的过程

在这里插入图片描述

编译

在这里插入图片描述
在这里插入图片描述

目标文件(*.OBJ)是我们对一个源程序进行编译要得到的最终结果。

列表文件(*.LST)是编译器将源程序编译为目标文件的过程中产生的中间结果。

交叉引用文件(*.CRF)同列表文件一样,是编译器将源程序编译为目标文件过程中产生的中间结果。

对源程序的编译结束,编译器输出的最后两行告诉我们这个源程序没有警告错误必须要改正的错误

提示语法错误

在这里插入图片描述
两类错误:
1.Severe Errors。
2.找不到给出的源程序文件。

命令后加;以简化过程。

连接

在这里插入图片描述

在这里插入图片描述

可执行文件(.EXE)是我们对一个程序进行连接要得到的最终结果。

映像文件(.MAP)是连接程序将目标文件连接为可执行文件过程中产生的中间结果。

库文件(.LIB)里包含了一些可以调用的子程序,如果我们的程序中调用了某一个库文件中的子程序,就需要在连接的时候,将这个库文件和我们的目标文件连接到一起,生成可执行文件。

no stack segment,一个“没有栈段”的警告错误 ,可以不理会这个错误。

在这里插入图片描述

连接中可能会遭遇错误例:object nor found —— 找不到对象

在这里插入图片描述
命令后加 ; 以简化过程

执行可执行程序

在这里插入图片描述
我们的程序没有像显示器输出任何信息。程序只是做了一些将数据送入寄存器和加法的操作,而这些事情,我们不可能从显示屏上看出来。
程序执行完成后,返回,屏幕上再次出现操作系统的提示符。

小结

在这里插入图片描述


三、运行及跟踪

在这里插入图片描述

Debug装载程序

在这里插入图片描述
程序被装入内存的什么地方?
在这里插入图片描述

  • 程序加载后,DS中存放着程序所在内存区的段地址,这个内存区的偏移地址为 0 ,则程序所在的内存区的地址为:DS:0。
  • 这个内存区的前256 个字节存PSP,DOS用来和程序进行通信。
  • 从 256字节处向后的空间存放的是程序,CS的值为DS+10H。
  • 程序加载后,CX中存放代码的长度(字节)。
    在这里插入图片描述

用Debug 单步执行

在这里插入图片描述

P命令和G命令

  • 继续命令P(Proceed):类似T命令,逐条执行指令、显示结果。但遇子程序、中断等时,直接执行,然后显示结果。
  • 运行命令G(Go):从指定地址处开始运行程序,直到遇到断点或者程序正常结束。
    在这里插入图片描述

执行的不同方式

在这里插入图片描述

四、[……]和(……)

[……]与(……)的约定

在这里插入图片描述
[…]——(汇编语法规定)表示一个内存单元

指令段地址偏移地址操作单位
mov ax,[0]在DS中在[0]中
mov al,[0]在DS中在[0]中字节
mov ax,[bx]在DS中在[bx]中
mov ax,[0]在DS中在[bx]中字节

(…)——(为学习方便做出的约定)表示一个内存单元或寄存器中的内容;…只能用寄存器及物理地址

描述对象描述方法描述对象描述方法
ax中的内容为0010H(ax)=0010H2000:1000处的内存为0010H(21000H)=0010H
mov ax,[2]的功能(ax)=((ds)*16+2)mov [2],ax的功能((ds)*16+2)=(ax)
add ax,2 的功能(ax)=(ax)+2add ax,bx的功能(ax)=(ax)+(bx)
push ax的功能(sp) = (sp)-2((ss)*16+(sp))=(ax)pop ax的功能(ax)=((ss)*16+(sp)
((ss)*16+(sp))=(ax)(sp)=(sp)+2

符号idata表示常量

例:

mov ax,[idata]:代表mov ax,[1]、mov ax,[2]、mov ax,[3]…
mov bx,idata:代表mov bx,1、mov bx,2、mov bx,3…
mov ds,idata:代表mov ds,1、mov ds,2…(都是非法指令)


五、Loop指令

  • 功能:实现循环(计数型循环)
    指令的格式:
    loop 标号

  • CPU 执行loop指令时要进行的操作
    ① (cx)=(cx)-1;
    ② 判断cx中的值
    不为零则转至标号处执行程序如果为零则向下执行。

  • 要求
    cx 中要提前存放循环次数,因为(cx)影响着loop指令的执行结果
    要定义一个标号

例:本程序功能2->4->8->16->32->…
在这里插入图片描述

用Loop指令编程实例

编程计算2^16
在这里插入图片描述
用cx和loop 指令相配合实现循环功能的三个要点:
(1)在cx中存放循环次数
(2)用标号指定循环开始的位置;
(3)在标号和loop 指令的中间,写上要循环执行的程序段(循环体)。

在这里插入图片描述
在这里插入图片描述

t命令和p命令的区别

继续命令P(Proceed):类似T命令,逐条执行指令、显示结果。但遇子程序、中断等时,直接执行,然后显示结果。
运行命令G(Go):从指定地址处开始运行程序,直到遇到断点或者程序正常结束;G命令还可以指定执行到的代码地址
在这里插入图片描述
在这里插入图片描述

循环是否越界

问题:计算ffff:0006字节单元中的数乘以3,结果存储在dx中
在这里插入图片描述


六、段前缀的使用

引入段前缀:一个“异常”现象及对策

在这里插入图片描述

Debug 中,mov al,[0]的功能是–将DS:0存储单元的值传给AL。
在这里插入图片描述
编译(masm)并连接(link)后…
在这里插入图片描述
编译好的程序中,mov al,[0]变成了将常量0传给AL。

  • 对策:
    在[idata]前显式地写上段寄存器
    mov ax,2000h
    mov ds,ax
    mov bx,0
    mov al,ds:[bx]
    mov ax,2000h
    mov ds,ax
    mov al,ds:[0]

  • 小结(在程序中):
    mov al,[0]:(al)=0,同mov al,0
    mov al,ds:[0]:(al)=((ds)*16+0)
    mov al,[bx]:(al)=((ds)*16+(bx))
    mov al,ds:[bx]:与mov al,[bx]相同

这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”或“es:”,在汇编语言中称为段前缀。

访问连续内存单元—loop和[bx]联手

问题:计算ffff:0~ffff:b字节单元中的数据的和,结果存储在dx中。

  • 分析:
    (1)运算后的结果是否会超出 dx 所能存储的范围?
    ffff:0~ffff:b内存单元中的数据是字节型数据,范围在0~255之间,12个
    这样的数据相加,结果不会大于 65535,可以在dx中存放下。
    (2)是否可以将 ffff:0~ffff:b中的数据直接累加到dx中?
    add dx, ds:[addr] ;(dx)=(dx)+?
    期望:取出内存中的8位数据进行相加
    实际:取出的是内存中的16位数据
    (3)是否可以将 ffff:0~ffff:b中的数据直接累加到dl中?
    add dl, ds:[addr] ;(dl)=(dl)+?
    期望:取出内存中的8位数据相加
    实际:取出的是内存中的8位数据,但很有可能造成进位丢失。
  • 对策:取出8位数据,加到16位的寄存器。
    mov al, ds:[addr]
    mov ah, 0
    add dx, ax
    在这里插入图片描述
    这样写的程序显然是太笨了,如和改进?
    改进:用loop循环
  • 方法:
    循环次数由CX控制
    循环中要访问的内存单元的偏移地址放到 bx中,随循环递增,访问连续的内存单元。
    在这里插入图片描述

段前缀的使用

问题:将内存ffff:0~ ffff:b中的数据拷贝到 0:200~0:20b单元中。
在这里插入图片描述


七、在代码段中使用数据

上面说到的将内存ffff:0~ ffff:b中的数据拷贝到 0:200~0:20b单元中。这样做是非常危险的。

  • 问题:
    程序中直接写地址,危险!
    安全”位置存放数据,存哪里?

  • 对策:
    在程序的段中存放数据,运行时由操作系统分配空间。
    段的类别:数据段、代码段、栈段
    各种段中均可以有数据
    可以在单个的段中安置,也可以将数据、代码、栈放入不同的段中

应用案例

  • 问题:编程计算以下8个数据的和,结果存在ax 寄存器中
    0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H

在代码段中定义数据
在这里插入图片描述在这里插入图片描述

dw: define word,定义字型数据
db 定义一个字节
dd 定义一个双字

问题:
在这里插入图片描述
真正的代码从0010开始在这里插入图片描述
在这里插入图片描述

解决问题的关键:让数据从CS:0000开始,让代码从CS:0010开始!
改进:
在这里插入图片描述
效果:程序加载后,CS:IP指向要执行的第一条指令在start处!
在这里插入图片描述
在这里插入图片描述


八、在代码段中使用栈

在代码段中使用栈:以数据逆序存放为例

问题:完成下面的程序,利用栈,将程序中定义的数据逆序存放。
在这里插入图片描述

  • 思路:
    程序运行时,定义的数据存放在cs:0~cs:F单元中,共8个字单元。
    依次将这8个字单元中的数据入栈,然后再依次出栈到这 8 个字单元中,从而实现数据的逆序存放。
    栈需要的内存空间,在程序中通过定义“空”数据来取得。

数据逆序存放程序

在这里插入图片描述在这里插入图片描述在这里插入图片描述


九、将数据、代码、栈放入不同段

在这里插入图片描述

  • 评价此方法:
    特点:数据,栈,代码都在一个段。
    问题:程序显得混乱,编程和阅读时都要注意何处是数据,何处是栈,何处是代码。
    只应用于要处理的数据很少,用到的栈空间也小,加上没有多长的代码。
    对策:数据,栈,和代码放在不同段。

这里是引用
在这里插入图片描述

总结

到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

区间图着色问题:贪心算法设计及实现

区间图着色问题:贪心算法设计及实现 1. 问题定义2. 贪心算法设计2.1 活动排序2.2 分配教室2.3 算法终止 3. 伪代码4. C语言实现5. 算法分析6. 结论7. 参考文献 在本文中,我们将探讨如何使用贪心算法解决一个特定的资源分配问题,即区间图着色问…

【深度学习-番外1】Win10系统搭建VSCode+Anaconda+Pytorch+CUDA深度学习环境和框架全过程

专栏的老读者们都知道,以前的文章以使用MATLAB的为多。 不过后续陆续开始展开深度学习算法的应用,就会逐渐引入Python语言了(当然MATLAB的代码也会同步更新),这是由于在深度学习领域,Python应用更为广泛。…

Matlab|【复现】主动配电网故障定位方法研究

目录 1 主要内容 算例模型 期望故障电流状态函数 评价函数(膨胀率函数) 算例验证方法 详实的文档说明 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序方法复现了《基于改进多元宇宙算法的主动配电网故障定位方法研究》_郑聪,建…

在ELF 1开发环境中使用Qt Creator进行远程调试

Qt Creator是一款跨平台集成开发环境(IDE),主要适用于支持Qt框架的各类应用程序开发。其内置的远程调试机制使得开发者能够在本地开发环境中对部署在远程设备上的代码进行调试,无需直接对远程设备进行操作。Qt Creator会通过网络连…

2.Vue简介

Vue简介 Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,V…

在 Linux 中删除文件和文件夹

目录 ⛳️推荐 前言 删除文件 🏋️练习文件删除 小心删除 删除目录 🏋️练习文件夹删除 测试你的知识 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到…

VSCode搭建内核源码阅读开发环境

0. 参考链接 使用VSCode进行linux内核代码阅读和开发_vscode阅读linux内核-CSDN博客 1. 搭建Linux内核源码阅读环境 现状,Linux内核源码比较庞大文件非常多,其中又包含的众多的宏定义开关配置选项,这使得阅读内核源代码称为一件头疼的事。 …

电脑工作者缓解眼部疲劳问题的工具分享

背景 作为以电脑为主要工作工具的人群,特别是开发人员,我们每天都需要长时间紧盯着屏幕,进行代码编写、程序调试、资料查询等工作。这种持续的工作模式无疑给我们的眼睛带来了不小的负担。一天下来,我们常常会感到眼睛干涩、疲劳…

[笔试强训day02]

文章目录 BC64 牛牛的快递DP4 最小花费爬楼梯[编程题]数组中两个字符串的最小距离 BC64 牛牛的快递 BC64 牛牛的快递 #include<iostream> #include<cmath> using namespace std;double a; char b;int main() {cin>>a>>b;int ans0;if(a<1.0){ans20;…

Go程序设计语言 学习笔记 第十三章 低级编程

Go的设计保证了一系列安全性&#xff0c;限制了Go程序可能出现问题的方式。在编译期间&#xff0c;类型检查会检测到大多数试图将操作应用于不适合其类型的值的尝试&#xff0c;例如&#xff0c;从一个字符串中减去另一个字符串。严格的类型转换规则阻止了直接访问内置类型&…

数字接龙(蓝桥杯)

文章目录 数字接龙【问题描述】解题思路DFS 数字接龙 【问题描述】 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏&#xff0c;游戏在一个大小为N N 的格子棋盘上展开&#xff0c;其中每一个格子处都有着一个 0 . . . K − 1 之间的整数。游戏规则如下&#xff1a; 从左上…

【图解计算机网络】从浏览器地址输入到网页显示的整个过程

从浏览器地址输入到网页显示的整个过程 整体流程DHCPhttp协议报文组装DNSTCP协议封装与TCP三次握手IP协议封装与路由表MAC地址与ARP协议交换机路由器 整体流程 从往浏览器输入一个地址到网页的显示&#xff0c;要经过很长的一个流程&#xff0c;中间涉及到计算机网络的许多知识…

力扣-LCP 02.分式化简

题解&#xff1a; class Solution:def fraction(self, cont: List[int]) -> List[int]:# 初始化分子和分母为 0 和 1n, m 0, 1# 从最后一个元素开始遍历 cont 列表for a in cont[::-1]:# 更新分子和分母&#xff0c;分别为 m 和 (m * a n)n, m m, (m * a n)# 返回最终的…

VOJ 等边三角形 题解 DFS

等边三角形 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; int n, flag 0, sum 0, tag; int length[20]; // 木棍长度 int group[3] {0}; // 三条边的当前边长 void dfs(int i, int index) {group[index] length[i];if (group[1] &g…

2024蓝桥杯嵌入式模板代码详解

文章目录 一、STM32CubeMx配置二、LED模板代码三、LCD模板代码 一、STM32CubeMx配置 打开STM32CubeMx&#xff0c;选择【File】->【New Project】&#xff0c;进入芯片选择界面&#xff0c;搜索到蓝桥杯官方的芯片型号&#xff0c;并点击收藏&#xff0c;下次直接点击收藏就…

React【Day4】

路由快速上手 1. 什么是前端路由 一个路径 path 对应一个组件 component 当我们在浏览器中访问一个 path 的时候&#xff0c;path 对应的组件会在页面中进行渲染 2. 创建路由开发环境 # 使用CRA创建项目 npm create-react-app react-router-pro# 安装最新的ReactRouter包 …

第64天:服务攻防-框架安全CVE复现Apache ShiroApache Solr

目录 思维导图 案例一&#xff1a;Apache Shiro-组件框架安全 shiro反序列化 cve_2016_4437 CVE-2020-17523 CVE-2020-1957 案例二&#xff1a;Apache Solr-组件框架安全 远程命令执行 RCE&#xff08;CVE-2017-12629&#xff09; 任意文件读取 AND 命令执行&#xff08…

建筑楼宇VR火灾扑灭救援虚拟仿真软件厂家

在传统消防安全教育方式中&#xff0c;往往存在内容枯燥、参与度低和风险大等问题&#xff0c;使得消防安全知识难以深入人心。然而&#xff0c;借助VR消防安全逃生教育系统&#xff0c;我们可以打破这一困境&#xff0c;为公众带来前所未有的学习体验。 VR消防安全逃生教育系统…

Java多线程-API

常见API一览 Thread t1 new Thread(() -> {System.out.println("我是线程t1");System.out.println("Hello, World!"); }); t1.start(); // 获取线程名称 getName() // 线程名称默认是Thread-0, Thread-1, ... System.out.println(t1.getName());// 通过…

AI 语音机器人系统怎么搭建

搭建AI语音机器人系统通常包括以下几个关键步骤&#xff1a; 确定需求和技术选型&#xff1a;首先要明确AI语音机器人需要实现的功能&#xff0c;选择合适的技术框架和工具&#xff0c;如自然语言处理工具、语音识别工具等。 搜集和准备数据&#xff1a;收集和整理与业务相关…