8086汇编实验(十题可用)
一、前言
1、这学期学8086汇编,所做的四次实验十个题目(前8手写,后2摘录后修改,时间久远未找到原文链接,愿理解),亲测可用,码住,希望能对将来的读者有所帮助。
2、有的需要在debug中根据段地址和偏移地址修改(e命令)或查看(d命令)值以后才能使用,偏移地址大多在3000,根据需要可能在3100也有,需要读源代码加以理解。
二、环境(DOSBox)
按照这篇文章配置。
三、题目及源代码
0.0、0.1为常用的两个功能,不是具体题目,也不是原创。
0.0 第一个helloworld!
.model small ;小型存储模式.stack ;定义堆栈段.data ;定义数据段
string db 'Hello, world!' ;预存字符串、db 0dh, 0ah, '$' ;回车换行结束 .code ;定义代码段
start: mov ax, @data ;装数据段(段mov ds, ax ; 地址送DS)lea dx, string ;调用21H号mov ah, 9 ; 中断,显示int 21h ; 字符串mov ax, 4c00h ;调用21H号中int 21h ; 断,返回end start ; 结束汇编
0.1 输入输出
.model small.stack.data
buf db 20db ?db 20 dup(0)
crlf db 0dh,0ah,'$'.code
start: mov ax,@datamov ds,axlea dx,buf;接受字符串mov ah,0ahint 21hmov al,buf+1add al,2mov ah,0mov si,axmov buf[si],'$'lea dx,crlf;另取一行mov ah,09hint 21hlea dx,buf+2;输出数据mov ah,9int 21hmov ax,4c00hint 21h
end start
1、十进制转二进制
.model small
SSTACK SEGMENT STACKDW 64 DUP(?)
SSTACK ENDS
DATA SEGMENT
SADD DB 33H,39H,32H,34H,30H ;
DATA ENDS
CODE SEGMENTASSUME CS:CODE, DS:DATA
START: MOV AX, DATA
MOV DS, AX
MOV AX, OFFSET SADD
MOV SI, AX
MOV BX, 000AH
MOV CX, 0004H
MOV AH, 00H
MOV AL, [SI]SUB AL, 30H
A1: IMUL BXMOV DX, [SI+01]AND DX, 00FFHADC AX, DXSBB AX, 30HINC SILOOP A1
A2: JMP A2
CODE ENDSEND START
2、asc转bcd
.model small.stack.data
crlf db 0dh,0ah,'$'.code
start: mov ax,@datamov ds,axmov ax,0mov cx,5mov si,34ffhjmp changenotin: dec cxmov al,0ffhmov [si+0ah],aljcxz ending
change: inc simov al,[si]cmp al,30hjb notincmp al,39hja notinand al,0fhmov [si+0ah],alloop changeending: mov ax,4c00hint 21hend start
3、循环程序设计
.model small.stack.data.code
start: mov ax,@datamov ds,axmov ax,2mov cx,3mov si,1
cheng: mul cxcmp ax,200ja endingadd si,axmov ax,cxinc cxjmp chengending: mov ax,4c00hint 21hend start
4、统计符号为负个数
.model small.stack.data
crlf db 0dh,0ah,'$'.code
start: mov ax,@datamov ds,axmov dx,0mov si,3000hmov cx,[si]mov ch,0mov si,1jmp tongjitemp: inc dxdec cxjcxz endingtongji: mov al,[si+3000h]inc sicmp al,127ja temploop tongjimov [si+3000h],dxending: mov ax,4c00hint 21hend start
5、冒泡排序
.model small.stack.data
buf db 10 dup(0)
crlf db 0dh,0ah,'$'.code
start: mov ax,@datamov ds,axmov ah,1mov cx,10mov si,0
gets: mov al,[si+3000h]mov buf[si],alinc siloop getsmov bx,9cmp ah,0jz ending
wai: mov ah,0mov cx,bxmov si,0
cmp_ad: mov al,buf[si]mov dl,buf[si+1]cmp al,dljb backxchg al,dlmov ah,1
back: mov buf[si],almov buf[si+1],dlinc siloop cmp_addec bxjnz waiending: mov cx,10mov si,0
print: mov al,buf[si]mov [3100h+si],alinc siloop printmov ax,4c00hint 21hend start
6、排名
这个比较懒,拿来排序前后的数据对应一下数值得到名次。
.model small.stack.data
buf db 10 dup(0)
buf2 db 10 dup(0)
crlf db 0dh,0ah,'$'.code
start: mov ax,@datamov ds,axmov cx,10mov si,0
gets: mov al,[si+3000h]mov buf[si],almov buf2[si],alinc siloop getsmov bx,9wai: mov cx,bxmov si,0
cmp_ad: mov al,buf[si]mov dl,buf[si+1]cmp al,dlja backxchg al,dl
back: mov buf[si],almov buf[si+1],dlinc siloop cmp_addec bxjnz waimov cx,10mov bx,0mov si,0cmp2: mov al,buf[bx]mov dl,buf2[si]cmp al,dljz writeinc bxloop cmp2write: inc bxmov [si+3100h],bxmov bx,0inc simov cx,10cmp si,10jb cmp2ending: mov ax,4c00hint 21hend start
7、求最大最小值
这个也是太懒辽,还是直接拿来冒泡排序后取头尾,大家知道就好,处理大量数据可千万不要这样。
STACK SEGMENT PARA STACK
SPAE dw 20 DUP(?)
TOP EQU SIZE SPAE
STACK ENDS
DATA SEGMENT
COUNT dw 7
DATA ENDS
MAIN SEGMENTASSUME CS:MAIN,DS:DATA,SS:STACK
STR: mov ax, DATAmov DS, axmov si, 3000Hmov cx, COUNTcall FAR PTR QIUhlt
MAIN ENDS
PROCE SEGMENTASSUME CS:PROCE,DS:DATA,SS:STACK
QIU PROC FARpush sipush cxpush bxpush bpmov bp, sppushfmov bh, [si]mov bl, bh
A1: inc simov al, [si]cmp al, bhjle ALBHmov bh, al
ALBH: cmp al, blje ALBLmov bl, al
ALBL: loop A1mov ax, bxpopfpop bppop bxpop cxpop siret 0
QIU ENDP
PROCE ENDSEND STR
8、求阶乘
STACK SEGMENT PARA STACK
SPAE dw 20 DUP(?)
TOP EQU SIZE SPAE
STACK ENDS
DATA SEGMENT
NUM dw 0
RESULT dw ?
DATA ENDS
MAIN SEGMENTASSUME CS:MAIN,DS:DATA,SS:STACK
STR: mov ax, DATAmov DS, axmov sp, size SPAEmov bx, NUMcall FAR PTR QIUhlt
MAIN ENDS
PROCE SEGMENTASSUME CS:PROCE,DS:DATA,SS:STACK
QIU PROC FARand bx, bxjz A1push bxdec bxcall QIUpop bxmul bxmov RESULT, axret
A1: mov ax, 1ret
QIU ENDP
PROCE ENDSEND STR
9.1、8259_1,编写中断程序,每次脉冲输出7
data segmentstring db "7",0DH,0AH,'$' ;回车+换行
data endscode segmentmain proc farassume cs:code,ds:datastart:mov ax,datamov ds,ax ;初始化数据段push ds ;通过数据段访问中断向量表mov ax,0000hmov ds,axmov ax,offset MIR7 ;取中断入口地址mov si,003ch ;中断矢量地址mov ds:[si],ax ;存放中断矢量mov ax,cs ;段地址mov si,003eh ;中断段地址mov ds:[si],ax ;存放中断段地址CLI ;关中断pop ds ;恢复数据段段地址init:;初始化8259mov al,11h;边沿触发out 20h,al;ICW1mov al,08hout 21h,al;ICW2mov al,04hout 21h,al;ICW3,IR2连接从片mov al,01hout 21h,al;ICW4mov al,6fh;不屏蔽ir7,ir4out 21h,al;OCW1STI;开中断AWAIT:nopjmp AWAIT ;无限循环MIR7:STIcall delay lea dx,stringmov ah,09hint 21h ;输出7mov al,20hout 20h,al ;中断结束iret ;中断返回main endpdelay proc nearmov cx,0a00hwaitPress:noploop waitPressretdelay endp
code endsend start
9.2、8259_2
根据老师要求,两个中断程序,分别输出sun,chen,因为有嵌套和delay函数,还可能出现显示字母混杂的情况(也是为了满足要求,感觉这个纯粹是为了捣乱)。
stack segmentdw 100 dup(?)tos label word
stack ends
data segmentstrings db "s$"stringu db "u$"stringn db "n",0DH,0AH,"$"stringc db "c$"stringh db "h$"stringe db "e$"string1 db "n",0DH,0AH,"$"
data ends
code segmentassume cs:code,ds:data,ss:stackmain proc farstart:mov ax, stackmov ss,axmov sp,offset tosmov ax,datamov ds,ax;初始化数据段push ds;通过数据段访问中断向量表mov ax,0mov ds,axmov ax,offset MIR7mov si,003ch;中断矢量地址mov ds:[si],ax;存放中断矢量mov ax,cs;段地址mov si,003eh;中断段地址mov ds:[si],ax;存放中断段地址mov ax,offset SIR1mov si,00c4hmov ds:[si],axmov ax,csmov si,00c6hmov ds:[si],axpop ds;恢复数据段段地址cli;关中;初始化主片8259mov al,11h;边沿触发out 20h,al;ICW1mov al,08hout 21h,al;ICW2mov al,04hout 21h,al;ICW3,IR2连接从片mov al,01hout 21h,al;ICW4mov al,6bh;主片OCW1,不屏蔽ir7,ir4,ir2out 21h,al;OCW1;初始化从片8259mov al,11hout 0a0h,al;ICW1mov al,30hout 0a1h,al;ICW2mov al,02hout 0a1h,al;ICW3mov al,01hout 0a1h,al;ICW4mov al,0fdhout 0a1h,al;从片OCW1sti;开中断Exam:nopjmp ExamMIR7:sticall delaylea dx,stringsmov ah,09hint 21hcall delaylea dx,stringumov ah,09hint 21hcall delaylea dx,stringnmov ah,09hint 21hmov al,20hout 20h,al;中断结束iret;中断返回SIR1:sti;call delay;延时防抖lea dx,stringcmov ah,09hint 21h;输出S1;call delaylea dx,stringhmov ah,09hint 21h;输出S1;call delaylea dx,stringemov ah,09hint 21h;call delaylea dx,string1mov ah,09hint 21hmov al,20hout 0a0h,alout 20h,al;中断结束iret;中断返回main endpdelay proc nearmov cx,0ff00hwaitButton:noploop waitButtonretdelay endpcode endsend start
10、8255键盘扫描
MY8255_A EQU 0600H
MY8255_B EQU 0602H
MY8255_C EQU 0604H
MY8255_CON EQU 0606HSSTACK SEGMENT STACKDW 16 DUP(?)
SSTACK ENDS DATA SEGMENTDTABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07HDB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA
START:MOV AX,DATAMOV DS,AXMOV SI,3000HMOV AL,00HMOV [SI],AL ;清显示缓冲MOV [SI+1],ALMOV [SI+2],ALMOV [SI+3],ALMOV DI,3003HMOV DX,MY8255_CON ;8255控制字初始化MOV AL,81H ;1000 0001 A、B口输出 C口输入OUT DX,ALBEGIN: ; 调用显示子程序 CALL DIS ;清屏 CALL CLEAR ;扫描 看是否有键按下CALL CCSCAN ;有键按下 跳INK1JNZ INK1 JMP BEGININK1: CALL DISCALL DALLYCALL DALLYCALL CLEARCALL CCSCAN; 若结果不为0 ZF=0 则说明一定有键按下 则跳转 判断哪个键按下JNZ INK2 JMP BEGIN;确定按下键的位置
INK2: MOV CH,0FEH ; FEH=1111 1110(对应关系:PA7 PA6..PA1 PA0 ) ; PA5-PA0=1111 10 (这里对应关系要弄明白) ;PA0对应的按键则是 从左到右第一列(这里不会晕哦) MOV CL,00H ; 初始对于行的偏移量 为0 ;列循环 即扫描列 从第一列开始
COLUM: MOV AL,CHMOV DX,MY8255_A OUT DX,AL MOV DX,MY8255_C IN AL,DX
L1: TEST AL,01H ;is L1?JNZ L2MOV AL,00H ;L1JMP KCODE
L2: TEST AL,02H ;is L2?JNZ L3MOV AL,04H ;L2JMP KCODE
L3: TEST AL,04H ;is L3?JNZ L4MOV AL,08H ;L3JMP KCODE
L4: TEST AL,08H ;is L4?JNZ NEXTMOV AL,0CH ;L4; 找到按键后 此时AL存的的第一列每一行的初始值 0 4 8 C
; CL 存的是对应行的偏移量
; 假设 AL为08H CL为2 则表示的总偏移量为 8+2=10H
; 说明在table中该数字的偏移量为10H
; 输出该数字 利用偏移量就行 因为数字其实是存在table中的
KCODE: ADD AL,CLCALL PUTBUFPUSH AX
KON: CALL DISCALL CLEARCALL CCSCANJNZ KONPOP AX
NEXT: INC CL ; CL相当于 行偏移量MOV AL,CHTEST AL,08H ; 08H=0000 1000 当AL为1111 0111 && 0000 1000 结果为0 ; ZF=1 说明行偏移量达到最大值 3JZ KERR ; 4次列循环结束 跳KERRROL AL,1MOV CH,ALJMP COLUM
KERR: JMP BEGIN; 键盘扫描子程序
; 原理是 先向全部列输出低电平
; 然后从C口读入 行电平
; 如果没有按键按下 所有行应该均为高电平
; 反之 若有按键按下 则开始仔细判断出到底是哪个按键按下 具体判断方法是:
; 先向第一列输出低电平(从左到右)
; 然后从C口读入行电平 利用 AND
; 判断哪一行是否为低电平即可(后面为了计算方便取反了行电平)
; 若行全为高 为开始向下一列输出低电平 循环4次即可
CCSCAN: MOV AL,00H MOV DX,MY8255_A OUT DX,AL ; 向所有列输出 低电平MOV DX,MY8255_C IN AL,DX ;读所有行电平;原来没有任何键按下 4行全为1;这里取反 变成 0000 便于后面的判断NOT AL; 假设没有按键按下 ; 0000&1111=0; 结果为0 ZF=1 AND AL,0FHRET;清屏子程序
;就是使得所有的灯熄灭 00H表示全不亮 瞬间 很快
CLEAR: MOV DX,MY8255_B MOV AL,00HOUT DX,ALRET; 显示子程序 (这里稍微有点绕)
DIS: PUSH AX MOV SI,3000H; 0DFH=1101 1111 对应PA7 PA6 PA5...PA1 PA0; 由电路图 得出 X1-PA0 X2-PA1.....; 6个显示器 从左到右依次是 X1 X2 X3... X5 X6; 所以 对应的PA: PA0 PA1 PA2...PA4 PA5; 这里初始是0DFH 代表 1 1 1 1 1 0 ; 意思是 第六个显示 开始显示数字; 哈哈 这里其实是从X6到X1依次显示的; 每个数字显示间隔很快 我们会认为是6个数字一起显示 其实是逐个显示MOV DL,0DFHMOV AL,DLAGAIN: PUSH DX; 把AL送给A口 觉得开放哪个灯 (这里要看电路图 A口也控制灯的开放)MOV DX,MY8255_A OUT DX,ALMOV AL,[SI] ; 把3000H--3005H中存的偏移量(相对)取出MOV BX,OFFSET DTABLE ; 获取DTABLE的首地址AND AX,00FFH ;因为后面会有加法运算 先把ah清0 这样ax就是 ; al的值,防止出错ADD BX,AX ; 获取需要的值的偏移量(这个是绝对偏移量)MOV AL,[BX] ; 获取显示数字需要的值 例 显示0需要3FHMOV DX,MY8255_B ; 送往B口 显示数字OUT DX,ALCALL DALLY ;延时INC SI ;移动SI 读取下一个偏移量POP DXMOV AL,DL ; DL: 控制哪个灯的开放 开始是0DF 1101 1111; 取后6位(看电路图 只连了6根线)即01 1111; 赋值给ALTEST AL,04H ; 测试AL 看是否为11 1110 ; 6个灯 一次显示需要循环6次; 这里第六次结束是 AL=11 1110; 对于灯 就是x1灯显示完(灯:X6->X1)JZ OUT1 ; 6次循环完成后 跳出ROR AL,1 ; 循环右移; 例 第一个灯亮 AL=01 1111 ; 则 第二个灯亮 为 10 1111; 所以需要循环右移; 反映在灯上 则是左移(不要绕进去了哦)MOV DL,ALJMP AGAIN ; 跳回 继续显示 需循环6次
OUT1: POP AXRET; 子程序 延时作用 RET为子程序结束标记
DALLY: PUSH CX MOV CX,0006H
T1: MOV AX,009FH
T2: DEC AXJNZ T2LOOP T1POP CXRET; 将获得的偏移量存入3000H--30005H中
; 便于后面的显示
; 显示其实就是从3000H--3005H中读取偏移量
; 然后在table中找到真正的值即可
PUTBUF: MOV SI,DI ;存键盘值到相应位的缓冲中MOV [SI],AL ;先存入地址3005H 再递减 也就是下一个存入偏移量的是3004HDEC DICMP DI,2FFFHJNZ GOBACKMOV DI,3003H
GOBACK: RETCODE ENDSEND START
建议实验可以用这些代码,考试用的话还是找一些比较简短的代码,确实这个8255和8259真的难记。
我们考试还常常带上数模转换器一起考,提示注意,不同学校未必有用。
8086汇编实验(十题可用)相关推荐
- 串操作指令及其应用程序的设计与调试运行——汇编实验四 用8086汇编完成下题 编制一程序,从键盘输入两个长度不同的字符串,设字符串长度小于25个字符。要求在屏幕上以右边对齐的形式显示出
文章目录 实验目的和内容 实验要求和步骤 实现右对齐 以下为源码: 方法一 方法二 方法三 测试一--字符串的输入输出 测试二--改进 测试三--改进 测试四--改进 实验目的和内容 实验要求和步骤 ...
- 8086汇编-实验1、2-debug调试命令
1.R命令 查看CPU寄存器的内容 -r 查看所有寄存器的内容 -r reg 改变制定寄存器中的内容 2.D命令 查看内存中的内容 -d 查看内存中的128个内存单元 -d 段地址:偏移地址 可查看指 ...
- 8086汇编-实验8-jmp指令的理解
offset 标号:取标号处的地址 mov 16位 offset 标号:取标号偏移地址 mov 32位 offset 标号:取标号段地址:偏移地址 assume cs:code code segmen ...
- 8086汇编-实验10-字符打印程序
效果如图: assume cs:codeparameters_stack segment ;程序断点参数传递db 48 dup(0) parameters_stack endsraw_stack se ...
- 8086汇编-实验9-字符打印
环境:DosBox 0.74-3,masm 效果如图: assume cs:codestack segmentdb 16 dup(0) stack endsalpha segment ;+26db ' ...
- 8086汇编-实验7-制表
assume cs:codestack segment ;栈段dw 0,0,0,0,0,0,0,0 stack endsdata segment ;属性db 1,'year',' num',' sum ...
- 8086汇编-实验6(微调)-小写转换大写
效果如下 代码如下 assume cs:codedata segmentdb '1. one 'db '2. two 'db '3. three 'db '4. four 'db '5. five ' ...
- 8086汇编-实验5(微调)-用栈实现数据交换位置
初始状态: 代码如下: assume cs:code,ds:data,ss:stackdata segmentdw 0123h,1234h,2345h,3456h,4567h,5678h,6789h, ...
- 8086汇编-实验4-[bx]和loop的使用
结果如下: 代码如下: code segment assume cs:code start:mov ax,0hmov ds,ax ;段地址初始化mov bx,200hmov di,0h ;偏移地址初始 ...
最新文章
- 道路场景语义分割算法
- gitee提交代码_在Gitee获8.5k Star,做微信小程序商城看这一个开源项目就够了
- c#启动EXE文件(简单的)
- C++ deque方法
- facenet训练自己的数据_基于SSD与Facenet的人脸识别
- ADS-B显示终端5.9
- ## __VA_ARGS__ ... 宏和可变参数
- Git 的安装、使用、分支、命令 一篇博客全都学会
- 31寸Aoc显示器写代码真香!包邮送一台!
- (117)System Verilog类继承详解
- SSH/SSH客户端介绍、利用SSH访问linux、SSH跟telnet区别
- 8.线性回归之非线性回归
- Conjugate function and Fenchel’s duality theorem
- 理论篇:如何理解51%攻击
- 分享到QQ、新浪微博、微信代码
- 人际沟通交流技巧(转)
- mysql查询and和or同时使用
- 类的封装继承多态以及virtual interface-SV
- SparkStreaming整合Kafka(0.8.2.1)计算不同业务指标并实现累加(结合Redis)
- SER 语音情感识别-论文笔记3