汇编学习笔记->输出月份缩写

编译环境:emu8086
附:ASCII码表
https://baike.baidu.com/item/ASCII/309296?fr=aladdin

datas   segment para    'data'
three   db      3     ;JUN等是3个字母的,因此在数组定位中,每3个字节是一个月
mess    db      'Input month number',13,10,'$'
monin   label   byte  ;为数据段中定义的下一个变量提供不同的名称和大小属性,共享同一个内存位置,label伪指令自身不分配内存
    max db  1         ;最多输入的字符数
    act db  0         ;在读入缓冲区时,此位置会自动存储输入数字的位数
    mon db  3 dup(0)  ;存储输入的数字,最多2个数字+1回车
    ;
    alfmon  db  '>>>',13,10,'$'   ;作为缓冲区使用,这里的>>>可以替换成别的字符,如?代表随机填入。
    montab  db  'JAN','FEB','MAR','APR','MAY','JUN'
            db  'JUL','AUG','SEP','OCT','NOV','DEC'
datas   ends

codes   segment para    'code'
    assume cs:codes,ds:datas,es:datas
    ;关联段与段寄存器,编译软件对assume不生成机器码 
start:
main    proc    far
    push    ds
    mov     ax,0
    push    ax
    
    mov     ax,datas
    mov     ds,ax
    mov     es,ax
    ;Input month
    lea     dx,mess         ;输出提示信息
    mov     ah,09
    int     21h             ;执行这条指令时,al的值会改变成24,原因是中断时al会返回刚刚输出的字符,输出的字符$的ASCII码就是24H
    
    lea     dx,monin   
    mov     ah,0Ah          ;键盘输入到缓冲区,(DS:DX+2)=输入字符串起始地址
    int     21h
    
    mov     DL,13           ;回车->回到当前行的行首
    mov     ah,02           ;显示输出,DL=输出字符
    int     21h
    
    mov     DL,10           ;换行->移动到下一行的相同位置
    mov     ah,02           ;显示输出,DL=输出字符
    int     21h
    
    ;cmp的功能相当于减法指令,cmp不保存结果,只影响符号位。sub指令执行过后ax被赋为减法的结果
    cmp     act,0           ;用act减去0,判断输入的数字位数是否为0(直接回车,就退出)
    je      exit            ;若ZF=1->减法运算结果全为0 则跳转
    
    ;Convert ASCII to binary
    mov     ah,30h          ;set up month
    cmp     act,2           ;用act减去2,判断输入的数字位数是否为2
    je      two             ;若ZF=1->减法运算结果全为0 则跳转
    mov     al,mon
    jmp     conv
two:
    mov     al,mon+1
    mov     ah,mon
conv:
    xor     ax,3030h        ;由于0的ascii码为30,所以要减去30才能获得对应的数字
    cmp     ah,0            ;Month 01-09?    是否输入了01,02,03这样的形式
    jz      loc             ;输入了02等形式,直接跳转到loc代码段
    sub     ah,ah           ;ah寄存器置0
    add     al,10           ;al寄存器中的值+10
    
    ;Locate month in table
loc:          
    lea     si,montab       ;取得月份缩写数组的地址
    dec     al              ;数组从0开始
    mul     three           ;每个月份缩写占3个字节,移动到下一个月份需要移动3个字节
    add     si,ax           ;定位到对应月份缩写的地址
    mov     cx,03           ;设置循环次数为3
    cld                     ;将标志寄存器Flag的方向标志位DF清零。在字串操作中使变址寄存器SI或DI的地址指针自动增加,字串处理由前往后
    lea     di,alfmon       ;取得待输出变量的地址到di中
    rep     movsb           ;重复movsb指令3次      movsb字符传送指令,将DS:SI的字节复制到ES:DI指向的地址。此处是将月份缩写数组中 3个缩写字母复制到待输出区中
    
    ;Display alpha month
    lea     dx,alfmon       ;将待输出区的地址存到dx中,即将调用09功能输出月份缩写
    mov     ah,09
    int     21h
    jmp     start           ;重复
exit:   
    mov     ah,4ch
    int     21h
main    endp  
codes   ends
end     main   

一些语句的解释:

  1. label
    name label type
    为数据段中定义的下一个变量提供不同的名称和大小属性,共享同一个内存位置,label伪指令自身不分配内存。在本代码中可以视为用monin来作为输入缓冲区内存地址的名字,在mov dx,monin并调用输入功能时,系统会根据内存地址开始第一个字来设置最大可输入的字符数(包括回车,回车必须要占用1个字符数),月份的数字最多是2位+1位回车符,因此max设置为3。第二个字用于存储实际输入字符的个数,在输入字符后,系统会自动将第二个字赋值为实际输入字符的个数(此处回车不会算入其中,如果直接回车,那么act是0,在后续cmp act 0会调用退出代码)。第三~n个字作为输入的缓冲区,系统会将输入的字符存储到第三个字开始的地址中(回车也会被存储进去),本代码中缓冲区从第3个字开始到第6个字(包含)结束,因此最多2个数字+回车。
    具体看代码中的注释

  2. cmp
    cmp的功能相当于减法指令,cmp不保存结果,只影响符号位。sub指令执行过后ax被赋为减法的结果。如果减法的结果为0,则会将ZF置为1

  3. je
    je code如果ZF=1,则跳转到语句code

  4. rep
    先将循环次数存入cx,重复(cx)次语句。注意:每循环一次cx会自动减1

  5. cld
    将标志寄存器Flag的方向标志位DF清零。在字串操作中使变址寄存器SI或DI的地址指针自动增加,字串处理由前往后。

  6. movsb
    movsb字符传送指令,将DS:SI的字节复制到ES:DI指向的地址。在本代码中是将月份缩写数组中 3个缩写字母复制到变量alfmon(待输出区)中

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值