• 汇编实验十(王爽)


    设计子程序

    子程序一:在指定的位置,用指定的颜色,显示一个用0结束的字符串

    举例:在屏幕的8行3列,用绿色显示data段中的字符串

    assume cs:code
    
    data segment
        db 'Welcome to masm!',0
    data ends
    
    code segment
    start:   mov dh,8     ;行
             mov dl,3     ;列
             mov cl,2     ;颜色属性
             mov ax,data
             mov ds,ax
             mov si,0
             call show_str  ;子程序
    
             mov ax,4c00h
             int 21h
    
    show_str:
             push dx   ;避免寄存器冲突(虽然这个子程序没有冲突,但为了更好的使用,还是加上了)
             push cx
             push si  
            
             mov ax,0b800h  
             mov es,ax   ;显示缓冲区段地址
             mov al,dh
             mov bl,0a0h  ;用于计算第八行的首地址
             dec al      
             mul bl    ;首地址在ax中
             mov bx,ax  ;存在bx寄存器内
             mov dh,0
             mov di,dx  ;用于计算列地址
             dec di
             add di,di ;列地址就在di寄存器中
             mov al,cl
          s: mov cl,ds:[si] ;取出字符,要判断cx是否为0
             mov ch,0
             jcxz ok  ;终止指令跳转的条件
             mov dl,ds:[si]   ;取出字符
             mov es:[bx+di],dl   ;将字符送入显示缓冲区中
             mov es:[bx+di+1],al  ;设置字符属性
             inc si     ;data段的地址偏移+1
             add di,2   ;显是缓冲区段地址+2
             jmp short s ;指令跳转
    
         ok: 
             pop si  ;恢复主程序中寄存器的值
             pop cx
             pop dx
             ret   ;子程序返回
    code ends
    
    end start

    运行结果:(不知明原因,第一行会被吃掉,因此实际显示是在第七行)

    子程序二:

    功能:解决除法溢出问题

    应用举例:计算1000000/10(F4240/0AH)

    返回: (dx) = 结果的高16位,(ax)=结果的低16位,(cx)=余数

    结果:(dx) =0001H, (ax)=86A0H,(cx)=0 

    公式:

    H:X的高16位

    L:X的低16位

    N:除数

    X/N = int(H/N)*65535 + [rem(H/N*65535)+L]/N

    (对公式的理解很重要!!!我看了半天,才看懂了)

    assume cs:code
    
    
    code segment
    start:  mov ax,4240h  ;存放被除数(dword类)的低16位地址
            mov dx,000fh   ;存放被除数(dword类)的高16位地址
            mov cx,0ah     ;存放除数
            call divdw
    
    divdw: 
            push ax   ;把ax(即低16位地址先存入栈中,之后要用到)
    
            mov ax,dx  ;对高16位地址进行16位除法
            mov dx,0
            div cx
            mov bx,ax ;bx的值为int(H/N),将除法所得商移入bx中
            pop ax    ;取出低16位地址
        
    div cx ;对低16位地址进行16位除法,结果的低16位商位于ax寄存器中 mov cx,dx ;将余数移入cx中 mov dx,bx ;将结果的高16位商移入dx中 ret code ends end start

     运行结果:

     子程序设计三:

    功能:将word型数据转变为表示十进制数据的字符串,字符串以0结尾

    应用举例:将12666以十进制的形式在屏幕的8行3列,用绿色显示出来(显示时调用子程序一)

    assume cs:code
    
    data segment
        db 10 dup(0) ;保存字符串的内存地址段
    data ends
    
    
    code segment
    start:      mov ax,12666
                mov bx,data
                mov ds,bx
                mov si,0
                call dtoc  ;调用子程序
    
                mov ax,4c00h
                int 21h
    
    dtoc:       mov bx,10   ;bx为除数
                mov dx,0    
                div bx    ;对ax进行16位除法
                mov cx,ax  ;商保存在cx中,用于结束除法的继续,当商为0时,代表所有余数已求出
                add dx,30h ;利用十进制对应的ascii码=十进制数值码+30H,得出字符并存在寄存器dx中
                push dx   ;将字符结果保存在栈中,因为余数结果相对于本身字符的顺序是逆序,因此我们要利用栈来逆序
                add si,1  ;记录除的次数,也就是字符的个数
                jcxz s1  ;若cx即商为0,则调到s1处
                jmp short dtoc  ;循环除法
    
                
    s1:         mov bl,0
                mov ds:[si],bl  ;在data段的即将放入字符的末尾,将0存入
                mov cx,si  ;将字符的个数存取cx中
                mov si,0   ;si寄存器表示data段的偏移地址
    s2:         pop ds:[si] ;取出放在栈中的数据
                add si,1   ;偏移地址+1
                loop s2  ;循环
    
                mov dh,8  ;显示字符串
                mov dl,3
                mov cl,2
                mov si,0
                call show_str
                ret
    
    show_str:    push dx
                 push cx
                 push si  
                
                 mov ax,0b800h
                 mov es,ax
                 mov al,dh
                 mov bl,0a0h
                 dec al
                 mul bl
                 mov bx,ax
                 mov dh,0
                 mov di,dx
                 dec di
                 add di,di
                 mov al,cl
              s: mov cl,ds:[si]
                 mov ch,0
                 jcxz ok
                 mov dl,ds:[si]
                 mov es:[bx+di],dl
                 mov es:[bx+di+1],al
                 inc si
                 add di,2
                 jmp short s
    
             ok: 
                 pop si
                 pop cx
                 pop dx
    
                 ret
    code ends
    
    end start

    运行结果:(还是一样,第一行显示的会被吃掉,所以实际在第七行)

  • 相关阅读:
    bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形【叉积+极角排序+瞎搞】
    poj 1286 Necklace of Beads【polya定理+burnside引理】
    poj 2154 Color【polya定理+欧拉函数】
    poj 2409 Let it Bead【polya定理+burnside引理】
    bzoj 3534: [Sdoi2014]重建【矩阵树定理】
    bzoj 1774: [Usaco2009 Dec]Toll 过路费【排序+Floyd】
    bzoj 4596: [Shoi2016]黑暗前的幻想乡【容斥原理+矩阵树定理】
    bzoj 4031: [HEOI2015]小Z的房间【矩阵树定理】
    poj Find a multiple【鸽巢原理】
    bzoj Strange Way to Express Integers【excrt】
  • 原文地址:https://www.cnblogs.com/jane315/p/12940541.html
Copyright © 2020-2023  润新知