![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
8086
汇编入门
马踏飞燕&lin_li
博客地址以迁移:https://linli1724647576.github.io/
展开
-
8086系列(24):实验3.6 键盘处理程序(2)
题目扩充键盘处理功能程序在示例3.6的基础上,增加left_shift和right_shift键的功能,即在按下left_shift键或right_shift键的同时,又按下0-9或a-z等键,则CPU显示的是键的上档符号或大写字母。思路和上一题类似,这一题增加处理的功能就是在kbint中断处理程序中判断是否按下了left_shift键或right_shift键。如何判断是否按下shift键呢,我们可以把按动状态记录在一个标志单元(kbflag1中),设按下right_shift键或按下left_s原创 2020-12-16 23:16:05 · 622 阅读 · 0 评论 -
8086系列(23):例3.6 键盘处理程序(1)
题目键盘处理程序思路该程序修改了键盘I/O,09号中断,并对键盘的按下和弹起进行中断检测,并把来自键盘的83个键的扫描码转换成相应的ascii字符。我们要知道事有:1、当键盘上“按下”或“放开”一个键时,如果键盘中断是允许的,就会产生一个9号中断2、键盘触点电路按照16×8=128矩阵排列每个按键分为“按下”和“放开”两种情况,通码:最高位为0断码:最高位为13、扫描码:一个字节,8位(256种情况),入60H号端口寄存器我们要做的事就是主程序:(1) 保存原来的09号中断向量原创 2020-12-16 22:44:16 · 764 阅读 · 0 评论 -
8086系列(22):中断响铃
题目编写一个中断处理程序,要求在主程序运行期间每隔 10秒响铃一次,同时显示‘The bell is ring!’思路代码;编写一个中断处理程序,要求在主程序运行期间,; 每隔 10秒响铃一次,同时显示‘The bell is ring!’datasg segment count dw 1 mess db 'The bell is ring!',0ah,0dh,'$'datasg endscodesg segmentmain proc far assume cs原创 2020-12-11 11:33:49 · 1750 阅读 · 3 评论 -
8086系列(21):作业6.9
题目编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及8个字符的电话号码,并以一定的格式显示出来思路主程序 TELIST:(1) 显示提示符INPUT_NAME:(2) 调用子程序INPUT_NAME输入姓名(3) 显示提示符INPUT A TELEPHONE NUMBER:(4) 调用子程序INPHONE输入电话号码(5) 调用子程序PRINTLINE显示姓名及电话号码子程序INPUT_NAME:(1) 调用键盘输入子程序GETCHAR,把输入的姓名存放在INBUF缓冲区中(1)原创 2020-12-02 23:22:15 · 405 阅读 · 0 评论 -
8086系列(20):十六进制到十进制的转换程序
题目十六进制到十进制的转换程序(通过寄存器传送变量),要求从键盘上输入0-FFFFH的十六进制正数转化为十进制数并在屏幕上显示出来。思路先写主程序框架,首先需要把输入的十六进制数(字符串)转化为二进制数存在bx中,然后将bx中的数十进制显示。代码;-------十六进制到十进制--------datasg segmentdatasg ends;----------------codesg segmentmain proc far assume cs:codesg,ds:dat原创 2020-12-02 21:50:05 · 2816 阅读 · 1 评论 -
8086系列(19):递归
题目将字符串反序输出思路用bx保存字符串str的首地址,每次递归调用revers,当遇到’$'符时返回,在返回的途中输出每个字符。代码datasg segment str db 'abcde','$'datasg ends;-----------------codesg segmentmain proc far assume cs:codesg,ds:datasg,es:datasgstart: push ds sub ax,ax push ax原创 2020-12-02 16:16:46 · 298 阅读 · 0 评论 -
8086系列(18):查找电话号码
题目1.题目:查找电话号码phone2.实验要求:(1)建立一个可存放50项的电话号码表,每项包括任命(20个字符)及电话号码(8个字符)两部分;(2)程序可接收输入人名及相应的电话号码,并把它们加入电话号码表中;(3)凡有新的输入后,程序应按照人名对电话号码表重新排序;(4)程序可接收需要查找电话号码的人名,并从电话号码表中查出其电话号码,再在屏幕上以如下格式显示出来。name tel.××× ×××3.提示:程序采用子程序结构。主程序的部分主原创 2020-11-21 09:20:12 · 2129 阅读 · 0 评论 -
8086系列(17):子程序参数传送----通过堆栈传送参数地址
题目题目和上一篇一样,都是累加数组中的元素。思路采用通过堆栈传送参数地址法的程序,是在主程序里把参数地址保存到堆栈中,在子程序里从堆栈中取出这些参数以达到传送参数的目的。必须注意,子程序结束时的RET指令应该使用带常数返回的指令,常数大小和保存到堆栈的地址相关,以便返回主程序后,堆栈能恢复原始状态不变。堆栈情况示意图,图中所示程序是far型的,Call的时候push进了cs和ip。为什么是bp? 因为bp默认的段地址是堆栈段,如果用其它如(bx)需要 ss:[bx]代码;;;;;;;;通过堆原创 2020-11-18 16:21:11 · 1880 阅读 · 0 评论 -
8086系列(16):子程序参数传送----通过地址表传送参数地址
题目题目和上一篇一样,都是累加数组中的元素。思路采用地址表传送参数,这种方法是在主程序中建立一个地址表,要把传送给子程序的参数存放在地址表中,然后把地址表的首地址通过寄存器BX传送到子程序中去。子程序通过地址表取得所需参数,并把结果存入指定的存储单元去。代码;;;;;;;;通过直接访问模块传递参数;;;;;;;;;;;datasg segment ary dw 1,2,3,4,5,6,7,8,9,10 count dw 10 sum dw ? table dw 3原创 2020-11-18 15:44:40 · 802 阅读 · 0 评论 -
8086系列(15):子程序参数传送----通过直接访问模块中的变量传递参数
题目主程序MAIN和过程PROADD在同一源文件中,要求用过程PROADD累加数组中的所有元素,并把和(不考虑溢出)送到指定的存储单元去。思路如果通过直接访问模块中的变量传递参数那么子程序就被写死了,如果要求再计算一次求和,那么子程序将无法复用,下一节将介绍第三种方法,通过地址表传送参数地址。代码;;;;;;;;通过直接访问模块传递参数;;;;;;;;;;;datasg segment ary dw 1,2,3,4,5,6,7,8,9,10 count dw 10 sum原创 2020-11-18 15:29:56 · 411 阅读 · 0 评论 -
8086系列(14):子程序参数传送----通过寄存器传送参数
题目十进制到十六进制数转换程序。程序要求从键盘取得一个十进制数,然后把该数以十六进制形式在屏幕上显示出来。思路主程序部分十分简单,调用一个子程序DECIBIN实现从键盘取得十进制数并把它转成二进制数;另一个子程序BINHEX把此二进制数以十六进制数显示出来。另外用CRLF子程序取得回车和换行的效果,BX寄存器用来在过程间传递要转换的数。代码;;;;;;;;通过寄存器传递参数;;;;;;;;;;;datasg segmentdatasg ends;----------------------原创 2020-11-18 15:15:08 · 825 阅读 · 0 评论 -
8086系列(13):跳跃表法
题目试根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支去。输入AL的第几位为1,输出转移到第几个分支。思路分支程序的实现方法主要有三种:第一种是菱形分支,可以直接用 jmp 类指令进行判断跳转第二种是逻辑尺,反应了每次要做的操作第三种就是跳跃表法。以下程序使用变址寻址的方式使用跳跃表法,还可以使用寄存器间接和基址变址方式来达到同一目的。代码datasg segment branch_table dw routine_1 d原创 2020-11-16 18:03:07 · 946 阅读 · 0 评论 -
8086系列(12):折半查找
题目在附加段中,有一个从小到大顺序排列的无符号数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组的长度。在AX中有一个无符号数,要求在数组中查找AX,如找到,CF=0,并在SI中给出该元素在数组中的偏移地址;如未找到,置CF=1思路折半查找过程如下:(1) 初始化被查找数组的首尾下标,low=1,high=n(2) 若low>high 则查找失败,置CF=1,退出程序否则计算中点 mid = (low+high)/2(3) ax与中点元素比较,若ax = r[mid] ,则查原创 2020-11-16 16:09:24 · 538 阅读 · 0 评论 -
8086系列(11):冒泡排序改进
题目给一个长度为n的数组进行冒泡排序。思路相较上一篇的冒泡排序,数组需要比较(N-1)遍,但是有时候比较的遍数未达(N-1)时就已经整序完毕,但程序必须运行到(N-1)次才能结束。为了提高效率,可以采用一个交换标志位,每次进入外循环就置交换标志位为1,在内循环中每做一次交换操作就置标志位为0,每次内循环结束后,可以测试交换标志位,如果该位为0,则交换过再次进入外循环,否则就立即结束外循环。代码datasg segment array dw 3,5,6,1,4,2,9,7,0,8 n原创 2020-11-16 15:15:15 · 280 阅读 · 0 评论 -
8086系列(10):冒泡排序
题目从键盘上输入任意个数字,存放在数组BUFFER中,编制程序使该数组中的数按照从小到大排序,最终输出结果。思路采用冒泡排序,从第一个数开始对相邻的两个数进行比较,如次序对,则不需要任何操作;如果次序不对,则交换两个数的位置。N个数第一轮需要比较(N-1)次,第二轮需要比较(N-2)次,比较(N-1)+(N-2) + … + 1 就可以完成冒泡排序。程序结构分为三个部分,输入部分、排序部分和输出部分,输入部分将十进制数不加转换地存入内存中,输出只需要将内存中的数以16进制数输出即可,这里并不需要判断原创 2020-11-15 09:31:36 · 1652 阅读 · 1 评论 -
8086系列(9):键盘控制输入
题目试着编制一程序,从键盘输入一行字符,要求第一个键入的字符必须是空格,如不是,则退出程序;如是,则开始接受键入的字符并顺序放在首地址为BUFFER的缓冲区中(空格不存入),直到接收到第二个空格符时退出程序。思路这一程序要求接受的字符从空格开始从空格结束,因此程序必须区分所接受的空格是不是第一个字符,设立标志位存储单元FLAG,一开始置为0,接受空格后置为1。代码datasg segment buffer db 80 dup(?) flag db ?datasg ends;--原创 2020-11-14 16:22:46 · 1515 阅读 · 0 评论 -
8086系列(8):逻辑尺
题目设有数组X和Y。X数组中有X1,…,X10;Y数组中有Y1,…,Y10。试编制程序计算Z1=X1+Y1,Z2=X2+Y2,Z3=X3-Y3,Z4=X4-Y4,Z5=X5-Y5,Z6=X6+Y6,Z7=X7-Y7,Z8=X8-Y8,Z9=X9+Y9,Z10=X10+Y10,结果存入Z数组。思路对于这种问题可以使用循环结构来完成,由于每次循环的操作位不同,我们可以事先设立标志位存放于逻辑尺中,进入循环后取出每一个位就可以判断做哪种操作了。代码datasg segment x dw 0,1,原创 2020-11-14 15:57:37 · 1799 阅读 · 1 评论 -
8086系列(7):字符串分类计数
题目从键盘输入一系列字符(以回车符结束),并按字母、数字及其他字符分类计数,最后显示出这三类的计数结果。思路分支的极致运用,按照ASCII码由小到大进行比较,有点麻烦。详细解释见代码。代码datasg segment ALPHABET db 'alaphabet:','$' NUMBER db 'number:','$' OTHER_ db 'other:','$' CRLF db 13,10,'$'datasg ends;------------codesg原创 2020-11-11 20:07:23 · 959 阅读 · 1 评论 -
8086系列(6):寻找数组A和B中相同的元素
题目已知数组A包含15个互不相等的整数,数组B包含20个互不相等的整数。试编制一程序,把既在A中又在B中出现的整数存放于数组C中。思路取出数组A中的元素放入AX,用串查找指令查找AX是否出现在数组B中,如果出现则放入数组C。在查找过程中涉及到二重循环,一是取出数组A中的元素,二是scasw在B查找,我都使用了cx计数器,做法是在scasw查找B之前先把cx push到堆栈里,之后再弹出。代码datasg segment array_A dw 0,1,2,3,4,5,6,7,8,9,10,1原创 2020-11-11 19:18:12 · 1424 阅读 · 0 评论 -
8086系列(5):数组中插入一程序
题目将正数N插入一个已整序的字数组的正确位置。该数组的首地址&末地址分别为ARRAY_HEAD和ARRAY_END,其中所有数均为正数且已按递增的次序排列。思路由于首地址和末地址已知,所以数组的长度是已知的,但是我们没有用到数组的长度,而是以找到插入的位置作为终止条件,这就需要我们在首地址前多放一个无穷小的字,确保可以插入到第一个位置以结束循环。我们从尾部向头部开始查找,如果没有找到插入的位置,就将该数往右移动一个单元,以此类推。代码datasg segment x dw ? a原创 2020-11-11 16:21:35 · 650 阅读 · 0 评论 -
8086系列(4):查找数组中的数并将其删除
题目在附加段中,有一个首地址为LIST的未经排序的字数组。在数组的第一个字中,存放着该数组的长度,数组的首地址已经存放在DI寄存器中,AX寄存器中存放着一个数。要求在数组中查找该数,如果找到将其从数组中删除。思路这一程序首先查找数组中是否有AX,如果没有则不对数组做任何处理就结束,如果找到这一元素,则把此数后的元素向前移动一个字,如果找到的元素正好位于数组末尾,则直接修改数组长度就可以了。这里巧妙地用到了串比较指令scasw,计数器cx在串比较指令完成后其实就是需要移动数组的个数。代码datas原创 2020-11-11 15:56:48 · 1497 阅读 · 0 评论 -
8086系列(3):统计Y中1的个数
题目在ADDR单元中存放着数Y的地址,试编制一程序把Y中的1的个数存入COUNT单元中思路可以从最高位开始判断是不是1,这里巧妙地用到了test指令,用 test ax,0ffffh,最高是不是1影响到了符号标志位SF,同时也可以判断后面是否全部为0,提高了效率。代码datasg segment addr dw number number dw 1010101010101010B count dw ?datasg ends;----------------codes原创 2020-11-11 09:41:57 · 998 阅读 · 0 评论 -
8086系列(2):查找匹配字符串
题目查找匹配字符串:程序接收用户键入的一个关键字以及一个句子。如果句子中不包含关键字则显示’No match!’;如果句子中包含关键字则显示‘Match’,且把该字在句子中的位置用十六进制数显示出来。思路(1) 输入关键字和一个句子,分别存入相应的缓冲区(2)在句子中查找关键字关键字和句子中相应字段的比较可以使用串比较指令,附加段和数据段定义为同一段,以便串指令的使用。下面说明比较过程中寄存器的使用情况:SI:存放原串首地址DI:存放目的串首地址CL:关键字长度 (keyword的长度原创 2020-11-07 16:30:12 · 1769 阅读 · 0 评论 -
8086系列(1): 试编制一个程序把BX寄存器中的二进制数用十六进制数的形式在屏幕上显示出来
题目例5.1 试编制一个程序把BX寄存器中的二进制数用十六进制数的形式在屏幕上显示出来。思路想要将BX中的值一位一位的显示,我们首先想到利用循环移位,然后取出每一位的数并转化为字符串进行显示。要如何移位呢?通过循环右移4位把最高字节的数移到最低位,然后与0fh相与,取出该位。设置cx计数器为4,移位4次就可以将BX中的数全部取出,这里涉及到了循环。要如何将每一位的数转化为ASCII码呢,可以看到0-9的ASCII码对应的是30H-39H,而A-F的ASCII码对应的是41H-46H。这必然要用原创 2020-11-07 14:10:22 · 6092 阅读 · 3 评论