汇编语言 实验三 循环结构和分支结构程序设计
一、编写程序把 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
来将bx
存array
第一个的偏移地址
也可以用到其他寻址方式,首先将bx
值0
(mov 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
文章评论