汇编语言 实验三 循环结构和分支结构程序设计
一、编写程序把 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
|