一、前言

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汇编实验(十题可用)相关推荐

  1. 串操作指令及其应用程序的设计与调试运行——汇编实验四 用8086汇编完成下题 编制一程序,从键盘输入两个长度不同的字符串,设字符串长度小于25个字符。要求在屏幕上以右边对齐的形式显示出

    文章目录 实验目的和内容 实验要求和步骤 实现右对齐 以下为源码: 方法一 方法二 方法三 测试一--字符串的输入输出 测试二--改进 测试三--改进 测试四--改进 实验目的和内容 实验要求和步骤 ...

  2. 8086汇编-实验1、2-debug调试命令

    1.R命令 查看CPU寄存器的内容 -r 查看所有寄存器的内容 -r reg 改变制定寄存器中的内容 2.D命令 查看内存中的内容 -d 查看内存中的128个内存单元 -d 段地址:偏移地址 可查看指 ...

  3. 8086汇编-实验8-jmp指令的理解

    offset 标号:取标号处的地址 mov 16位 offset 标号:取标号偏移地址 mov 32位 offset 标号:取标号段地址:偏移地址 assume cs:code code segmen ...

  4. 8086汇编-实验10-字符打印程序

    效果如图: assume cs:codeparameters_stack segment ;程序断点参数传递db 48 dup(0) parameters_stack endsraw_stack se ...

  5. 8086汇编-实验9-字符打印

    环境:DosBox 0.74-3,masm 效果如图: assume cs:codestack segmentdb 16 dup(0) stack endsalpha segment ;+26db ' ...

  6. 8086汇编-实验7-制表

    assume cs:codestack segment ;栈段dw 0,0,0,0,0,0,0,0 stack endsdata segment ;属性db 1,'year',' num',' sum ...

  7. 8086汇编-实验6(微调)-小写转换大写

    效果如下 代码如下 assume cs:codedata segmentdb '1. one 'db '2. two 'db '3. three 'db '4. four 'db '5. five ' ...

  8. 8086汇编-实验5(微调)-用栈实现数据交换位置

    初始状态: 代码如下: assume cs:code,ds:data,ss:stackdata segmentdw 0123h,1234h,2345h,3456h,4567h,5678h,6789h, ...

  9. 8086汇编-实验4-[bx]和loop的使用

    结果如下: 代码如下: code segment assume cs:code start:mov ax,0hmov ds,ax ;段地址初始化mov bx,200hmov di,0h ;偏移地址初始 ...

最新文章

  1. 道路场景语义分割算法
  2. gitee提交代码_在Gitee获8.5k Star,做微信小程序商城看这一个开源项目就够了
  3. c#启动EXE文件(简单的)
  4. C++ deque方法
  5. facenet训练自己的数据_基于SSD与Facenet的人脸识别
  6. ADS-B显示终端5.9
  7. ## __VA_ARGS__ ... 宏和可变参数
  8. Git 的安装、使用、分支、命令 一篇博客全都学会
  9. 31寸Aoc显示器写代码真香!包邮送一台!
  10. (117)System Verilog类继承详解
  11. SSH/SSH客户端介绍、利用SSH访问linux、SSH跟telnet区别
  12. 8.线性回归之非线性回归
  13. Conjugate function and Fenchel’s duality theorem
  14. 理论篇:如何理解51%攻击
  15. 分享到QQ、新浪微博、微信代码
  16. 人际沟通交流技巧(转)
  17. mysql查询and和or同时使用
  18. 类的封装继承多态以及virtual interface-SV
  19. SparkStreaming整合Kafka(0.8.2.1)计算不同业务指标并实现累加(结合Redis)
  20. SER 语音情感识别-论文笔记3

热门文章

  1. 4g网络设置dns地址_你还没搞明白凭啥就你的手机网络不佳连接超时?
  2. UI自动化+Java自动化脚本
  3. vue表单验证-正则表达式
  4. js无法获取数组长度
  5. 解决谷歌浏览器一键翻译无效问题
  6. 女生最喜欢的情人节礼物,华为nova高清图赏
  7. html显示上标,JavaScript sup 方法:把字符串显示为上标
  8. php 防止注入函数,php 防止SQL注入函数
  9. 外骨骼机器人(四):步态分析之基本知识
  10. 汽车部件IPX9K/IP69K、IP66K等ip防护等级测试的应用