• 几个汇编入门小例子


    一:打印 Hello World

    DATA SEGMENT  
        BUF DB 'HELLO WORLD!  THIS IS MY FIRST ASM FILE! $'  
    DATA ENDS  
    
    CODE SEGMENT  
        ASSUME  CS:CODE,DS:DATA  
    START:  
        MOV AX,DATA  
        MOV DS,AX  
    
        LEA DX,BUF  
    
        MOV AH,09H
        INT 21H  
    
        MOV AH,4CH  
        INT 21H  
    
    CODE ENDS  
    END START  
    

    小记:

    1. 字符串的最后一个字符必须是“$”

    2. LEA DX,BUF 等价于 MOV DX,OFFSET BUF

    3.通过功能号为 9 的DOS功能调用实现字符串的显示

    09H     显示字符串
    01H     单个字符的输入
    02H     单个字符的输出
    

    二:计算 ffff:0 ~ ffff:b 单元中的数据的和,存储在 dx 中。

    分析:

    1.运算结果是否会超出dx所能存储的范围?
    

    答:dx ,一个字,有两个字节,16位 ,范围在 0~65535 。ffff:0 ~ ffff:b**内存单元中的数据都是字节型数据**,范围在0~255之间,12个这样的数据相加不会超过65535 ,所以完全可以存放的下!

    ;实例:计算ffff:0~ffff:b 单元 中的数据的和 ,存储在dx中 。
    assume cs:TT 
    TT segment 
        start :
        mov ax,0ffffh
        mov ds,ax 
    
        mov dx,0  
    
        mov bx,0 
    
        mov cx,12 
    tag:
        mov al,[bx]
        mov ah,0
        add dx,ax 
        inc bx 
        loop tag 
    
        mov ax,4c00h
        int 21h 
    
        TT ends  
    end 

    小记:

    1. cx 用来控制 loop 循环次数

    2. 字节对应字节 ,字对应字 。

        mov al,[bx]
        mov ah,0
        add dx,ax 

    3.汇编中数据必须以0 开头,即 0ffffh ,而不能是 ffffh

    三:从键盘输入两个十进制数 ,然后以十进制数的形式输出他们的和 。

    分析:

    1.键盘输入得到他们的ASCII码值 
    2.减去30H,得到以非压缩型BCD数形式表示的十进制数字 
    3.相加并进行调整(AAA )
    4.再加上30H ,变为对应的ASCII码值 ,输出即可 
    
    
    DATA SEGMENT  
        INFOR1 DB  "Please input the frist data(<10):$"
        INFOR2 DB  0AH,0DH,"Please input the second data(<10):$" 
        INFOR3 DB  0AH,0DH,"The result is:$ " 
    DATA ENDS 
    
    CODE SEGMENT  
        ASSUME CS:CODE ,DS:DATA 
    START :
        MOV AX ,DATA
        MOV DS,AX
    
        MOV DX ,OFFSET INFOR1 ;显示提示信息 
        MOV AH,09H  
        INT 21H 
    
        MOV AH,01H ;接受输入 
        INT 21H  ;此时等待用户输入,输入的字符一定存放在AL中
        sub AL,30H 
    
        MOV BL,AL ;转移到 BL 
    
        MOV DX ,OFFSET INFOR2 ;显示提示信息 
        MOV AH,09H 
        INT 21H
    
        MOV AH,01H  ;另一个数放在 AL 中
        INT 21H
        sub AL,30H  
    
        MOV DX ,OFFSET INFOR3
        MOV AH,09H 
        INT 21H 
    
    
        XOR AH,AH ; 清零 AH ,CF标志位也会清零 
        add AL,BL  
        AAA  
    
        push AX 
        MOV  DL,AH 
        add DL,30H
        MOV AH,02H
        INT 21H
    
        pop AX 
        MOV DL,AL 
        add DL,30H 
        MOV AH,02H
        INT 21H
    
        MOV AX,4C00H
        INT 21H
    
    
        CODE ENDS
    END START 
    

    小记:

    1. 从键盘输入一个字符 (输入的字符一定存放在AL中

        mov AH,01H ;接受输入 
        int 21H  ;此时等待用户输入,输入的字符一定存放在AL中
        sub AL,30H 

    2. XOR XX,XX ; 清零 XX ,CF标志位也会清零

    3. 显示一个字符( 显示的一定是 DL中的内容 )

        mov AH,02H
        int 21H

    4.因为在途中将有些单词写为小写时出现了错误,所以建议全部写为大些形式 ,保证不会出错 !

    5.关于push ax 和 pop ax 。 说实话 ,我还不是很懂,所以不敢乱说 ~_~

    6.学习参考链接:(DOS功能调用一览表)https://blog.csdn.net/icurious/article/details/51628343

    四:将内存 ffff:0 ~ ffff:b 段元中的数据拷贝到 0:200 ~ 0:20b 单元中 , 0:200 ~ 0:20b 就等价于 0020:0 ~ 0020:b

    ASSUME CS:TT 
    TT SEGMENT 
    START:
        MOV BX,0 
    
        MOV CX,12
    s:  MOV AX,0FFFFH
        MOV DS,AX 
        MOV DL,[BX]
    
        MOV AX,0020H
        MOV DS,AX 
        MOV [BX],DL 
        INC BX 
        LOOP s
    
        MOV AX,4C00H
        INT 21H
    TT ENDS 
    END 

    因为每次循环要设置两次ds,效率会比较低下,所以我们来优化一下 :

    ASSUME CS:TT 
    TT SEGMENT 
    START:
    
        MOV BX,0 
        MOV AX,0020H
        MOV ES,AX
    
        MOV AX,0FFFFH
        MOV DS,AX 
    
        MOV CX,12
    s: 
        MOV DL,[BX]
        MOV ES:[BX],DL 
        INC BX 
        LOOP s
    
        MOV AX,4C00H
        INT 21H
    TT ENDS 
    END 

    小记:

    1. 因源单元和目标单元相距大于 64KB ,在不同的64KB段里,程序中,每次循环要设置两次ds

    2. 使用段前缀 MOV ES:[BX] , DL (其实也很简单了)

    3. 0:200h ~ 0:2FFh 共256个字节的空间(几乎不会被使用,什么都不会存放) 可以作为一段安全的空间任意使用

    五:将 data 数据段的数据通过栈的性质倒序存入

    ASSUME CS:TT,DS:DATA,SS:STACK  
    
    DATA SEGMENT  
        DW 0123H,0456H,0789H,0ABCH,0DEFH,0FEDH,0CBAH,0987H ;数据段原始数据
    DATA ENDS 
    
    STACK SEGMENT
        DW 0,0,0,0,0,0,0,0 
    STACK ENDS 
    
    TT SEGMENT 
    START:       ; CS:IP pointer here 
        MOV AX,STACK 
        MOV SS,AX 
        MOV SP,16 ;栈顶指针指向 16(2*8) 
    
        MOV AX,DATA
        MOV DS,AX 
    
        MOV BX,0
        MOV CX,8 
    tag:PUSH [BX]
        ADD  BX,2
        LOOP tag 
    
        MOV BX,0
        MOV CX,8
    s:  POP [BX]
        ADD BX,2
        LOOP s
    
        MOV AX,4C00H
        INT 21H
        TT ENDS 
    END START 

    小记:

    1.

     dw 即 define word  , 定义字型数据 
     db 即 define byte  , 定义字节型数据 
    

    2. DS,CS,SS,ES 不能直接给数据,必须通过通用寄存器(ax,bx,cx,dx )给他们赋值

    比如: MOV DS,DATA     会出错
    

    3. sp 一次移动两个单元(即一个字)

    4.

        push指令 –> ①SP-2 –> ②将**字型数据**存放到SS:SP地址中 
        pop指令 –> ①将SS:SP地址的**字型**数据取出来 –> ②SP+2 
    

    六:输入年龄(如果是三位数就直接输入即可,如果是两位数,第三位数写为0 。比如:032 ),输出其所对应的年龄段名称 。

    分析:

    1.得到三个数字字符
    2.先判断百位是不是 1,如果是1 ,在判断十位大不大于5 ,
      大于5,其他物种,小于5,是个老人啊 
    3.再判断百位是不是0 ,如果不是,其他物种,如果是,判断十位
        < 60 child  
        60~80 middle man 
        > 80 old man 
    
    
    DATA    SEGMENT
            INFOR1  DB 0AH,0DH,"Please  input your age :$"
            INFOR2  DB 0AH,0DH,"Your age is < 60 ,I think you are a child $"
            INFOR3  DB 0AH,0DH,"You are a middle man $"
            INFOR4  DB 0AH,0DH,"You are  a  old man $"
            INFOR5  DB 0AH,0DH,"You are a  other species !$" 
            AGE     DB 0,0,0
    DATA    ENDS
    
    CODE    SEGMENT
          ASSUME CS:CODE,DS:DATA
    START:  
            MOV  AX,DATA
            MOV  DS,AX
    
            MOV  DX,OFFSET INFOR1
            MOV  AH,09H
            INT 21H 
    
            MOV CX,3 
            MOV BX,OFFSET AGE 
        tag:
            MOV AH,01H  ;接受输入 
            INT 21H    ;此时等待用户输入,输入的 one ge 字符一定存放在 AL 中
            MOV [BX],AL  
            INC BX 
            LOOP tag 
    
            MOV BX,OFFSET AGE    
            CMP  [BX],BYTE PTR '1'
            JE   TEMP   ; == 1
    
            CMP BYTE PTR [BX],'0'
            JNE  OTHER  ; != 0 
    
            INC BX 
            CMP  [BX],BYTE PTR '6'
            JB CHILD 
    
            CMP  [BX],BYTE PTR'8'
            JB MAN 
            JNB OLD_MAN  
    
            JMP  PEND
        TEMP:
            INC BX
            CMP [BX],BYTE PTR'5'
            JNA OLD_MAN ; <= 5 
            JA OTHER   ; >5
        CHILD:
            MOV  DX,OFFSET INFOR2
            MOV  AH,09H
            INT 21H 
            JMP  PEND       ;注意执行完一个分支后应使程序跳出
        MAN:    
            MOV  DX,OFFSET INFOR3
            MOV  AH,09H
            INT 21H 
            JMP  PEND       
    
        OLD_MAN:    
            MOV  DX,OFFSET INFOR4 
            MOV  AH,09H
            INT 21H 
            JMP  PEND       
    
        OTHER:  
            MOV  DX,OFFSET INFOR5 
            MOV  AH,09H
            INT 21H 
            JMP  PEND       
    
        PEND:
            MOV  AH,4CH
            INT  21H
    CODE    ENDS
    END  START

    这里写图片描述

    小记:

    1.字与字节必须对应

        CMP  [BX],BYTE PTR '1'
        JE   TEMP   ; == 1
    

    2. 检测比较结果的条件转移指令( je 和 jz相同)

    je/jz     等于则转移         zf=1
    
    jne/jnz    不等于则转移     zf=0
    
    jb     低于则转移        cf=1
    
    jnb    不低于则转移    cf=0
    
    ja     高于则转移        cf=0且zf=0
    
    jna    不高于则转移    cf=1或zf=1
    

    助记:

        e : equal
    
        ne : not equal
    
        b: below ;在下面,到下面,低于;(表示位置)在…下面 
    
        nb : not below
    
        a : above ;表示程度)超过;(表示等级)在…之上;(表示位置)在…正上
    
        na : not above
    
  • 相关阅读:
    typedef和define的详细区别
    谈谈Android Activity的生命周期管理
    【Android面试】Android面试题集锦 (陆续更新)(最新2012618)
    [ZZ]Ubuntu<>Windows 远程桌面连接(debian等同)
    C语言中的全局变量内存分配和初始化顺序
    [刘未鹏]怎样花两年时间去面试一个人
    线程间通信常用的三种方法
    C语言const详解
    细雨寒风水冰 no
    C#读取*.sql文件,并执行里面的SQL语句 no
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335292.html
Copyright © 2020-2023  润新知