汇编教程4--学会解决问题
最近真的有点忙,又是c#,又是java,robocode,又是win32asm,
忙得不可开交了,不过教程不能耽误了,毕竟第一次写,有大家给我鼓励,
很知足了。
不知道上一片你们看得怎么样?看不懂也没关系,慢慢体会,我最开始的时候就看的是一大堆的寄存器,标志位,什么都不懂,如们还花了很多时间的。
正题。
一、循环结构:
1 循环指令。
格式:loop 指令标号
功能:将寄存器cx的值减去1。然后判断:如果cx<>0,这转移指令到标号处。否则继续执行后续指令。相当于以下两条指令:
dec cx
jnz 指令标号
所以要在循环前先确定循环次数,置入cx中。
注意:在循环体中不要对cx改写,至于原因我想我不必多说了吧。
来一段程序:
设变量var中有10个数据,12,0,-6,44,-54,0,3,51,98,69 统计其中0的个数。
现在我们学习重在分析了,不像以前重点理解语句。
10个数据,每个占用一个字节就可以了,那我们怎么样实现数据统计呢?应该用循环。有几个问题:
怎样逐个读入数据?从一个变量中。
比较后怎么样统计0的个数?
会不会重复统计?
解决了这几个问题这个程序也就出来了。
第一个问题,对于一个变量里的多个数据的读入,上一章讲过了,这就相当于一个数组,最常用的方法就是利用bx来寻址。
第二个问题,用一个专门的寄存器,统计0的个数
第三个问题,其实很简单,关键是不要把这个程序和冒泡法的算法搞混了,这个程序对于全部的数据只要循环一次就可以了。
ok,写出规划,这个很重要,刚刚学习的最好写一下,尤其是汇编,免得寄存器出错。很难查错的。
al:保存从变量读入的数据
bx:间接寻址用
cx:循环
dl:计数器,统计0的个数。
data segment
var db 12,0,-6,44,-54,0,3,51,98,69
result db ?
data ends
code segment
assume cs:code,ds :data
start:
mov ax,data
mov ds,ax
mov bx,0
mov dl,0
mov cx,10 ;上面一堆mov都是为了初始化
again:
mov al,[bx+var]
cmp al,0
jnz lab ;如果不等于0就转lab
inc dl ;如果读入的数为0,dl++
lab:
inc bx
loop again
mov result,dl
mov ah,4ch
int 21h
code ends
end start
it is a easy job,isn't?
这里有一个问题,因为前面我说了,10个数据,每个占用一个字节就可以了,那为什么循环计数不用cl或ch?这样不会浪费,别忘了,循环指令的默认操作对象就是cx,不能修改的。
在设计程序的时候,多注意寄存器的使用,初学者往往对怎么用乱而无序。
下面,来一段冒泡法的程序,我不解释,不懂的再问。
data segment
var db -1,-10,-100,27h,0ah,47h
n equ $-var
data ends
code segment
assume cs:code,ds:data
b mov ax,data
mov ds,ax
mov cx,n-1
mov dx,1
ag: call subp ;调用子程序
inc dx
loop ag
mov ah,4ch
int 21h
**************************;子程序开始
subp proc
push cx
mov cx,n
sub cx,dx
mov si,0
recmp: mov al,var[si]
cmp al,var[si+1]
jle noch
xchg al,var[si+1]
xchg al,var[si]
noch: inc si
loop recmp
pop cx ;
ret
subp endp
**************************
code ends
end b
有点难度,不过多看看一定会想通的,巩固一下,以后会比较深了。
2003 11月29日凌晨1:33
sssa2000