【Bug】8086汇编学习

文章目录

  • 随笔
  • Bug
    • 1、masm编译报错:Illegal use of register
    • 2、debug中使用段前缀
    • 3、[idata]在编译器中的处理
    • 4、push立即数报错
    • 5、报错:improper operand type
    • 6、程序莫名跳转到未知位置 (doing)
    • 7、DOSBox失去响应
    • 8、程序运行显示乱码
    • 9、程序运行导致DOSBox窗口自动关闭
    • 10、如何换行输出?
    • 11、公司收入项,仅输出了一行
    • 12、loop指令报错:jump out of range by 7 byte(s)
    • 13、忘记程序返回
    • 14、开始解析的位置不同,代码也不同
    • 15、中断例程安装与子程序调用
  • 问题
  • 想法

随笔

与汇编的灵活与底层所伴随的,是使用者极大的心智负担。

模块之间的隔离性很难控制。甚至多个子程序间的标号也不能相同,故子程序无法独立开发后直接集成。

cx是个高频冲突寄存器呢!

程序过度的复杂性,往往令我感到沮丧无力。多层的子程序、循环嵌套,也让程序的调试变得十分困难(甚至折磨),而此时我缺乏一个有效的调试工具。

寄存器的冲突、覆盖,真是频繁又隐晦的bug,产生令人摸不着头脑的效果。

2023-10-21

关于《汇编语言》(作者:王爽)的学习,就此告一段落了,最后一章(第17章)还剩一个实验,和一个课程设计。但磁盘读写好像在DOSBox中没用,做不了。此外还有一个“综合研究”部分,有空倒可以看看。这本书一共差不多花了40~50个小时吧,我阅读并验证了书中的大部分代码,做了书中的每一个实验(除了最后一章的),还算是有不少收获吧。能比较完整地啃下来一本书,也挺有成就感的,同时也能为日后的学习增添点自信心。

Bug

1、masm编译报错:Illegal use of register

mov es:bp.0[0]

报错的意思是:非法使用寄存器。代码应修改如下:

mov es:[bp].0[0]

2、debug中使用段前缀

在代码中可以这样写:

mov ax, es:[bx]

但在debug中不能直接这样写,要分两行:

es:
mov ax,[bx]

3、[idata]在编译器中的处理

在debug模式中可以直接使用[idata]的写法,如

mov ax,[6]

但如果是写在文件里要用编译器编译运行的,不能使用立即数,应当使用寄存器中转一下。

mov bx,6
mov ax,[bx]

4、push立即数报错

push 02h

会出现错误信息:Immediate mode illegal。应先将立即数放入寄存器,然后push寄存器。

mov ax,02h
push ax

5、报错:improper operand type

mov byte ptr es:[bx+di], [si]

其实是犯了一个老错误,mov不能直接将一个内存单元中的数据移动到另一个内存单元,而需要通过寄存器。因为cl是8位,指明了目标数据的尺寸,就不必使用byte ptr指明数据的尺寸。

mov cl, [si]
mov es:[bx+di], cl

6、程序莫名跳转到未知位置 (doing)

在这里插入图片描述

图中,在执行完命令div cx后,下一条指令迷路了。初步猜测是使用栈却未初始化spdebug程序对栈的借用导致的联动bug,但暂未仔细分析。完整代码如下:

assume cs:code code segment 
start:mov ax,4240hmov dx,000fhmov cx,0ah call divdw mov ax,4c00hint 21h;功能:进行不会溢出的除法运算,除数为word型,被除数、结果为dword型
;参数:(ax)=被除数的第6位, (dx)=被除数的高6位, (cx)=除数
;返回:(dx)=结果的高16位, (ax)=结果的低16位, (cx)=余数
divdw:push dx push ax mov bp,sp mov ax,[bp+2] div cx push ax mov ax,[bp]div cx mov cx,dx ;保存余数pop dxret
code ends end start

7、DOSBox失去响应

在运行自己编写的汇编程序后,DOSBox虚拟机就失去响应了。

  1. 员工数据段长度错误。
  2. 再次出现问题6:程序莫名跳到未知位置。

分析:在执行命令mov bx,[di+00ab]后,寄存器bx的值变为了0,随后导致div bx命令发生除0错误。因为员工数中少了一个数据,下一个数据被后面定义的0所覆盖,自然bx也变成了0。

为什么上次单独运行表格结构化程序,没有发现问题?

:那时后面没有紧接着定义一些0数据,可能后面的数据刚好不是0。虽然数据不对,但程序照常执行。(待核定)

在这里插入图片描述

8、程序运行显示乱码

原因:我在用于显示字符串的show_str子程序中,利用es寄存器存放目标显存的地址。而在主程序中es本来是指向存放表格数据的数据段,于是导致了冲突,数据乱了。

总而言之,是子程序的隔离性没有做好。可以在子程序开始时将es寄存器入栈保护现场,返回前再出栈恢复。

在这里插入图片描述

9、程序运行导致DOSBox窗口自动关闭

这bug真的是越修越离谱。运行程序k1,随后在指定的地方成功显示出绿色的"1975"字样,但在几秒的延迟后,窗口直接关闭了。

下面是我显示字符串的子程序。可以看到,使用了栈的命令包括:

push es
push cx
pop cx
pop es

看起来好像收支平衡,对栈的使用是正常的。然而,在结束循环时的jcxz ok命令,却会直接跳过一次pop cx。这下问题就大了!后面的pop es将会把原来cx寄存器的内容写入到es段寄存器中,然后,发生一些不为人知的事情,很可能就导致了程序的崩溃。

一个很容易想到的方法是,在pop es前添上一个pop cx,弥补这个过错。

; 6 子程序 - 显示字符串
;说明:显示一个以0结尾的字符串,在第y行,第x列,颜色为color,字符串起始位置为local
;参数:(dh)=y, (dl)=x, (cl)=color, ds:si=local
show_str:push es     ;避免与主程序冲突;绑定显存段mov ax,0b800hmov es,ax ;定位行mov al,0a0h mul dh mov bx,ax  ;定位起始列dec dladd dl,dl mov dh,0mov di,dx ;通用寄存器初始化mov ch,0s_show:;判断结尾push cx mov cl,[si] jcxz ok;写入一个字符,及其属性mov byte ptr es:[bx+di], cl pop cx mov es:[bx+di+1], cl ;循环迭代inc si add di,2jmp s_show;程序返回ok: pop esret

10、如何换行输出?

我本来的想法是在待输出的字符串中添加换行符,期待在输出的时候就会自动换行,但效果如下。

在这里插入图片描述

这才突然想到,我是通过直接向显存中写入数据,来输出字符的。这种方法并不会奏效。

11、公司收入项,仅输出了一行

年份是正常输出了,但收入一栏却仅输出了一行。猜测有两种可能:

  1. 输出坐标出错,所有收入都写在一行,覆盖了。
  2. 字符串早前就未正常写入待显示区。

我调整了循环次数,收入仍然仅输出一行,数字却发生了改变,变成了前一个数字,故大概率是第一种情况。

在这里插入图片描述

12、loop指令报错:jump out of range by 7 byte(s)

意思是循环体的长度超出了loop指令的最大范围,超出量为7个字节(注意一条指令通常并不是仅一个字节)。

由此我产生了两种想法:

  1. 使用我突发奇想的二级跳,从loop先跳到中间一个标签s0,再经过某种验证(刚刚是从后面的loop跳过来的,而不是从前面执行过来的)后,跳到循环开始的标签s处。
  2. 将一些重复度较高的指令封装为子程序,减少循环中显示的指令条数。

最后我都失败了,程序出现了莫名其妙的bug,未能解决。

13、忘记程序返回

代码的逻辑检查了好几遍,硬是感觉毫无bug。可在正常输出的时间信息后面还输出了一团乱七八糟的字符,并将DOSBox成功卡死。

最后发现,原来是忘了程序返回,也不知道怎么就导致了那一团东西出现在屏幕上。

mov ax,4c00h
int 21h

在这里插入图片描述

14、开始解析的位置不同,代码也不同

在这里插入图片描述

0000:0200开始的第一行汇编代码是jmp 020A,可顺着往下看,发现根本就没有从020A开头的代码。不过,如果直接从020A开始查看,同样的内存区间看到的又是另外一套代码。

在这里插入图片描述

15、中断例程安装与子程序调用

有一个利用了直接定址表编写的多功能子程序,我要将它安装成中断例程并使用,然而原本正常的程序却突然爆出bug。我步步为营,仔细地推断、分析后,总算还是让它正常跑起来了。最初的问题代码已在下面列出。

其实最后回头一看也就是几个小问题,可我真的找了好久才成功发现它们。

;安装中断例程7ch --> 200h
;bug版assume cs:code code segment 
start:;拷贝例程代码mov ax,cs mov ds,ax mov ax,0mov es,ax mov si,offset setscreen     ;ds:si源地址 mov di,200h                 ;es:di目的地址 mov cx,offset setscreenend-offset setscreencld rep movsb;设置中断向量表mov ax,0 mov es,ax mov word ptr es:[7ch*4], 200h       ;例程偏移地址mov word ptr es:[7ch*4+2], 0        ;段地址mov ax,4c00h int 21h;参数:(ah)=功能号
;说明:0清屏, 1设置前景色, 2设置背景色, 3向上滚动一行
setscreen:jmp short set table dw sub1,sub2,sub3,sub4set:push bx cmp ah,3 ja sret mov bl,ah mov bh,0 add bx,bx   ;根据功能号,计算在table中的偏移call word ptr table[bx]sret:pop bx retsub1:push bx push cx push es mov bx,0b800hmov es,bx mov bx,0  mov cx,2000sub1s:mov byte ptr es:[bx],' 'add bx,2 loop sub1s  pop es pop cx pop bx ret sub2:push bx push cx push es mov bx,0b800hmov es,bx mov bx,1 mov cx,2000 sub2s:and byte ptr es:[bx],11111000b or es:[bx],al add bx,2 loop sub2s pop espop cx pop bx ret sub3:push bx push cx push es mov cl,4 shl al,cl mov bx,0b800h mov es,bx mov bx,1 mov cx,2000 sub3s:and byte ptr es:[bx],10001111b or es:[bx],al add bx,2 loop sub3s pop es pop cx pop bx ret sub4:push cx push si push di push es push ds mov si,0b800h mov es,si mov ds,si mov si,160 mov di,0 cld mov cx,24 sub4s:push cx mov cx,160 rep movsb pop cx loop sub4s mov cx,80 mov si,0 sub4s1:mov byte ptr [160*24+si],' ' add si,2 loop sub4s1 pop ds pop es pop di pop si pop cx ret 
setscreenend:nopcode ends 
end start 

在这里插入图片描述

问题

  1. 10_s10_1.asm:运行效果:有些奇怪,第一行会多出同样的字符串,并在短暂延迟后上移消失。而我之前做过的显示程序都没有出现这样的现象,如10_t5.asm
  2. 如果子程序想要使用数据段内存,可不知道父程序是否会使用,如何避免冲突?

想法

  1. masm编译得到的.exe文件无法直接在我电脑上点击运行。我可以写一个脚本,自动打开DBox虚拟机,并在其中运行相应的程序吗?
  2. 写一个打字游戏?

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

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

相关文章

黑豹程序员-架构师学习路线图-百科:Java的第二春Spring框架

文章目录 1、 Spring的发展历史2、为什么Spring能霸屏?2.1、容器的设计2.2、通过四个策略2.3、三种方式 3、学习编程设计的典范 1、 Spring的发展历史 正当SUN公司的EJB在全球开始热炒时,正当程序员纷纷转型EJB开发时,正当程序员为跑通EJB程…

Node.js--》简易资金管理系统后台项目实战(后端)

今天开始使用 node vue3 ts搭建一个简易资金管理系统的前后端分离项目,因为前后端分离所以会分两个专栏分别讲解前端与后端的实现,后端项目文章讲解可参考:前端链接,我会在前后端的两类专栏的最后一篇文章中会将项目代码开源到我…

vulnhub靶机Funbox11

下载地址:Funbox: Scriptkiddie ~ VulnHub 主机发现 arp-scan -l 目标192.168.21.164 端口扫描 nmap --min-rate 1000 -p- 192.168.21.164 端口好多处理一下吧 nmap --min-rate 1000 -p- 192.168.21.164 |grep open |awk -F / {print $1} |tr \n , 端口服务版本…

冰蝎默认加密的流量解密

破解冰蝎的默认加密 流量包分析 上传的冰蝎流量包 POST /web-zh/DVWA/vulnerabilities/upload/ HTTP/1.1 Host: 192.168.197.111 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0 Accept: text/html,application/xhtmlxml,a…

文件读取结束的判定

大家好啊,我们今天来补充文件操作的读取结束的判定。 被错误使用的feof 牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾…

ArcGIS笔记9_数据源缺少空间参考信息?如何定义坐标系?

本文目录 前言Step 1 确定好要赋予给目标文件的恰当坐标系Step 2 定义坐标系 前言 有时从其他软件转换得到了shp文件,拖到ArcGIS后却出现“未知的空间参考:添加的数据源缺少空间参考信息 不能投影”的提示,如下图所示: 这种情况就…

图详解第六篇:多源最短路径--Floyd-Warshall算法(完结篇)

文章目录 多源最短路径--Floyd-Warshall算法1. 算法思想2. dist数组和pPath数组的变化3. 代码实现4. 测试观察5. 源码 前面的两篇文章我们学习了两个求解单源最短路径的算法——Dijkstra算法和Bellman-Ford算法 这两个算法都是用来求解图的单源最短路径的算法,区别在…

Rclone连接Onedrive

一、Rclone介绍 Rclone是一款的命令行工具,支持在不同对象存储、网盘间同步、上传、下载数据。 我们这里连接的onedrive,其他网盘请查看官方文档。 注意: 需要先在Windows下配置好了,然后再将rclone配置文件复制到Linux的rclone配…

【编解码】解码字符串中的 UNICODE 字符

前言 由于前后端交互中编码的问题,出现了这样的一串字符: {"share_names":["\u4e2d\u6587\u8def\u5f84"]}出现了unicode编码作为字符串内容的情况,直接用json解析的话会报错,所以在json解析前需要先进行转码…

每日刷题|贪心算法初识

食用指南:本文为作者刷题中认为有必要记录的题目 推荐专栏:每日刷题 ♈️今日夜电波:悬溺—葛东琪 0:34 ━━━━━━️💟──────── 3:17 &#x1f…

[ROS2系列] ORBBEC(奥比中光)AstraPro相机在ROS2进行rtabmap 3D建图

目录 背景: 一、驱动AstraPro摄像头 二、安装rtabmap error1:缺包 三、尝试 四、参数讲解 五、运行 error2: Did not receive data since 5 seconds! 六、效果​编辑 error4: 背景: 1、设备:pc;jeston agx …

使用VGG框架实现从二分类到多分类

一.数据集的准备 与之前的不同,这一次我们不使用开源数据集,而是自己来制作数据集。重点需要解决的问题是对数据进行预处理,如每一个图片的大小均不同,需要进行resize,还需要对每一张图片打标签等操作。 数据集文件 …

【Netty专题】【网络编程】从OSI、TCP/IP网络模型开始到BIO、NIO(Netty前置知识)

目录 前言前置知识一、计算机网络体系结构二、TCP/IP协议族2.1 简介*2.2 TCP/IP网络传输中的数据2.3 地址和端口号2.4 小总结 三、TCP/UDP特性3.1 TCP特性TCP 3次握手TCP 4次挥手TCP头部结构体 3.2 UDP特性 四、总结 课程内容一、网络通信编程基础知识1.1 什么是Socket1.2 长连…

微软 Win11 Dev 预览版 Build 23570 发布,修复文件资源管理器卡顿问题

本心、输入输出、结果 文章目录 微软 Win11 Dev 预览版 Build 23570 发布,修复文件资源管理器卡顿问题前言微软 Win11 Dev 预览版 Build 23570 发布,修复文件资源管理器卡顿问题完整的更新日志[Windows 中的 Copilot][开始菜单][任务栏搜索][设置] 已知问…

面向对象设计原则之依赖倒置原则

目录 定义原始定义进一步的理解 作用实现方法代码示例 面向对象设计原则之开-闭原则 面向对象设计原则之里式替换原则 面向对象设计原则之依赖倒置原则 面向对象设计原则之单一职责原则 定义 依赖倒置原则(Dependence Inversion Principle)&#xff0c…

【广州华锐互动】全屋智能家电VR虚拟仿真演示系统

在过去的几年中,智能家居的概念已经逐渐进入人们的生活。然而,它的真正潜力和最终形态可能还未被完全发掘。一种新兴的技术,虚拟现实(VR),为我们提供了一种全新的方式来理解和体验智能家居。VR公司广州华锐…

FFT64点傅里叶变换verilog蝶形运算,代码和视频

名称:FFT64点verilog傅里叶变换 软件:Quartus 语言:Verilog 代码功能: 使用verilog代码实现64点FFT变换,使用蝶形运算实现傅里叶变换 演示视频:http://www.hdlcode.com/index.php?mhome&cView&…

STM32F4X之GPIO

一、GPIO概述 主控芯片信息如下: 主频:168MHZ内核:ARM-M4FLASH:1MSRAM:192KB引脚:100GPIO:82电压:1.8~3.6V 1.1GPIO概念及其作用 GPIO概念:通用输入输出(General Purpose Input Output),主要作用…

How to add a jar to a project in eclipse?

Project -> Properties -> Java Build Path -> Libraries -> Add External JARs

前端多媒体处理工具——ffmpeg的使用

写在前面 在前端领域,FFmpeg 是一个非常有用的工具,它提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率切换等。可以在多种操作系统安装使用。 安装 下载FFmpeg 在网…