汇编语言 实验三 循环结构和分支结构程序设计

2022年2月4日 上午1:35 汇编语言

汇编语言 实验三 循环结构和分支结构程序设计

一、编写程序把 BX 寄存器内的二进制数用十六进制数的形式在屏幕上显示出来。

提示:参考书本p161-例5.1

思路

我们在将进制转换的时候是需要倒着处理的,BX是两个字节也就是16位,假如是1101011000111010,那么可以分成四位四位来看,也就是[1101][0110][0011][1010]对应的是D63A,我们倒着来就需要先处理前四位,那么我们将其左移四位(通过rol bx,cl指令)变成:
[0110][0011][1010][1101]
此时al存放的是低8位也就是[1010][1101],因为我们要处理后面四位,所以将al中的前4位置0,也就是用and al 0fh,这样让al[0000][1111]and,就可以达到。接着输出并且ch-1,继续左移,直到循环了四次,此时ch=0结束(jnz指令)
还需要注意的是:al需要加上30h(+48)变成ASCII码然后与3ah(也就是('9'+1),如果小于那么说明就是数字,如果大于的话那么我们需要输出字符,还得加上7h,然后再输出

代码

prognam segment     ;代码段
main proc far
    assume cs:prognam
start:
    push    ds
    sub ax,ax
    push    ax
    ;保留原数据
    mov ch,4    ;设置循环次数

    mov bx,34827    ;加入数据测试

rotate: mov cl,4
    rol bx,cl   ;bx 左移4位,先左移四位,可以达到从前往后处理
    mov al,bl   ;将bl给al bl有8位
    and al,0fh  ;将这8位的前4位置0
    add al,30h  ;+30H  +48
    cmp al,3ah  ;与'9'+1比较
    jl  printit ;小于0跳转printit
    add al,7h   ;+7再跳转printit
printit:
    mov dl,al   
    mov ah,2
    int 21h
    ;以上三行是输出
    dec ch
    jnz rotate  ;jnz不为0则转移
    ret     ;不然return掉
main    endp
prognam ends
    end

实验二 求ARRAY数组中最大值,并且以十六进制输出

提示:代码段、流程图如下

data    segment
    array   dw  4,6fffh,34,100,5ah,6b3h,1,0f234h,6,10
    n   dw  10
    max dw  ?
data    ends

在这里插入图片描述

思路

我一开始的思路是跟C++一样,用max来存最大值,实际上在汇编中需要用到寄存器来存,所以我们用ax来存第一个值,然后再一次扫一遍其他的,维护ax一直存的是最大的,如图所示。
我们可以用lea bx,array来将bxarray第一个的偏移地址
也可以用到其他寻址方式,首先将bx0mov bx,0),然后用类似数组的下标来操作,mov ax,array[bx]
因为array里面是dw,也就是双字节,所以我们bx每次移动是2位,也就是add bx,2,然后对ax和当前array的数进行比较,注意这里
我们思路是如果小于,那么就重置ax,在汇编中我选择用类似C++中的continue的做法,如果jg(大于)那么就跳转到skip执行循环操作,那么相反,如果小于的话那么就执行重置ax操作

;循环
s:  add bx,2
    cmp ax,[bx] ;比较ax 和当前
    jg  skip    ;greater
    mov ax,[bx]
skip:
    loop    s
;循环结束
    mov max,ax

最后转换成16进制还是用到第一个程序的代码

代码

data    segment
    array   dw  4,6fffh,34,100,5ah,6b3h,1,0f234h,6,10
    n   dw  10
    max dw  ?
data    ends
;-----------------data---------------
code    segment
    assume  cs:code,ds:data
start:
    mov ax,data
    mov ds,ax

    mov     ax,n
    dec ax
    mov cx,ax   ;cx=9 循环9次
    lea     bx,array    ;将array的首地址给bx
    mov ax,[bx] ;ax相当于我们所说的哨兵
;循环
s:  add bx,2
    cmp ax,[bx] ;比较ax 和当前
    jg  skip    ;greater  如果大于那么就是跳到skip进行循环
    mov ax,[bx] ;如果小于的话那么就重置ax
skip:
    loop    s
;循环结束
    mov max,ax


    mov bx,ax
    mov     ax,0
    mov ch,4
;开始转换
rotate: mov cl,4
    rol bx,cl   ;bx 左移4位
    mov al,bl   ;将bl给al bl有8位
    and al,0fh  ;将这8位的前4位置0
    add al,30h  ;+30H  +48
    cmp al,3ah  ;与'9'+1比较
    jl  printit ;小于0跳转printit
    add al,7h   ;+7再跳转printit
printit:
    mov dl,al   
    mov ah,2
    int 21h
    ;以上三行是输出
    dec ch
    jnz rotate  ;jnz不为0则转移
            ;不然return掉

    mov ax,4c00h
    int 21h
code    ends
    end start

实验三 将长度为count的str字符串按照从小到大的顺序排序并输出

参考:p172 例5.7
代码段给出如下:

data    segment
    str db  'qwertyuiopasdfghjklzxcvbnm',0dh,0ah,'$'
    count   dw  26
data    ends

思路

大致思路就是我们所学的冒泡排序,这里写一下易错的思路
1.这里代码段str是db,也就是单字节(8位),所以bx再增加的时候不再是上一个程序+2,而是add bx,1[bx+1],比较的时候不是ax了而是al
2.我们循环只能将cx--,而内层循环的时候会将外层循环的值也改变,所以我们需要在进行内层循环的时候将cx先保存起来,可以用mov di,cx先将cx的值放入di中,然后内存循环完毕之后cx=0,这时候将di中的值再给cx,这样内层循环完毕之后cx没有改变,然后进行的是loop中cx--的操作
3.xchg用法,交换,并且循环里面的al相当于我们交换里面的tmp
4.字符串输出,根据实验一里面的

mov ah,09h
lea dx,str
int 21h
mov ax,4c00h
int 21h

代码

data    segment
    str db  'qwertyuiopasdfghjklzxcvbnm',0dh,0ah,'$'
    count   dw  26
data    ends
;-------------------------data
code    segment
    assume  cs:code,ds:data
start:
    mov ax,data
    mov ds,ax

    mov cx,count
    dec cx
    lea bx,str  ;bx存str开始的偏移地址

loop1:  mov di,cx
    lea bx,str

loop2:  mov al,[bx]
    cmp al,[bx+1]
    jle continue    ;小于无需交换
    xchg    al,[bx+1]
    mov [bx],al
continue:   add bx,1
    loop    loop2

    mov cx,di
    loop    loop1

    mov ah,09h
    lea dx,str
    int 21h
    mov ax,4c00h
    int 21h

code    ends
;-------------------------------------------------------
    end start

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注