彙編實驗小記(五)-循環程序設計

  • 兩種循環結構
    • DO WHILE的循環結構用CMP指令和條件轉移指令構成
    • while少用
  • 循環指令:loop,loope,loopne
  • 僞指令 EQU 及操做符 '$'的使用
  • 多重循環中,能夠由內層循環向外層循環跳轉,或者直接向外層程序跳轉,可是不容許從外向內跳轉
  • 會用循環實現排序算法

1.寫出y=5!的程序段

loop指令

cpu執行loop指令的時候,要進行兩步操做算法

LOOP Lable
  • (cx)=(cx)-1
  • 判斷cx中的值,不爲零則轉至Lable執行,若是爲零,則向下執行

data segment
t db '0123456789ABCDEF'
info db 'y = 5! $'
data ends
code segment
assume cs:code,ds:data
start:
	mov ax,data
	mov ds,ax

	mov dx,offset info
	mov ah,9
	int 21h
			
	mov al,1 ;起始值:用於儲存乘積
	mov bl,2 ;乘數起始值

	mov cx,4 ; 2*3*4*5 總共進行4次乘法運算->循環次數
	s:
	mul bl ;5!=120 8位二進制足以表示,因此能夠放在al中,就不用ax了
	inc bl
	loop s

	mov bp,4 ;輸出爲4位數的16進制,因此須要輸出4次

	s1:   ;將結果按照16進制數輸出
	mov cl,4  ;右移位數
	rol ax,cl
	mov si,ax
	and ax,0fh

	mov bx,ax
	mov dl,t[bx] ;找到對應的16進制數並輸出
	mov ah,2
	int 21h

	mov ax,si ;每次在右移以前就先保存
	dec bp
	jnz s1 ;bp不爲0說明4位數尚未輸出夠,因此繼續

	mov ah,4ch
	int 21h

code ends
end start
複製代碼

2.查找出數組中的負數,並顯示位置id(起始位置從0開始)

1.LOOPZ/LOOPE指令

cpu執行loopz指令的時候,要進行兩步操做數組

LOOPZ/LOOPE Lable
  • (cx)=(cx)-1
  • 若CX!=0而且同時ZF=1 則轉至Lable執行,若是爲零,則向下執行

2.ZF--零標誌,稍後看debug中分步執行

本題使用:【⚠️棧-保存數據】

data segment
	t1 db 1,2,3,4,-5,255,127
	t db '0123456789ABCDEF' ;用於二進制計算後對應過來找16進制數
	info db 0dh,0ah,'the id of first negtuve number is : $'
	count equ $-t1
data ends
stack segment
	db 512 dup(?) ;使用棧段
stack ends
code segment
assume cs:code,ds:data
	start:

	mov ax,data
	mov ds,ax

	mov ax,stack
	mov ss,ax

	mov sp,512

	mov dx,offset info
	mov ah,9
	int 21h

	mov bx,0

	mov cx,count ;循環中每次自動(cx)=(cx)-1    
	s:
	mov al,t1[bx]
	inc bx 
	and al,80h
	loopz s ;判斷cx中的值,不爲零則轉至標號處執行,若是爲零,則向下執行

	dec bx ;因爲上面的循環中s進行了自增,咱們須要的指示數是從0開始,因此須要減1
	mov ax,bx  

	mov cx,4 ;轉化成4位的十六進制數進行輸出
	s1:
	push cx
	mov cl,4
	rol ax,cl
	mov si,ax
	and ax,0fh
	mov bx,ax
	mov dl,t[bx]

	mov ah,2
	int 21h

	mov ax,si
	pop cx
	loop s1

	add si,2
	
	mov ah,4ch
	int 21h

code ends
end start
複製代碼

分步調試看loopz的用法標尺-ZF

若CX!=0而且同時 ZR 則轉至Lable執行(繼續循環),若是爲NZ,則向下執行其餘程序代碼bash

ZF-零標誌

  • 1:ZR
  • 0:NZ

還未查找到負數的時候:oop

找到負數:spa

3.一、 查找CATI表中的字符@,找到後,輸出其所在位置

data segment
	t1 db '1234567890@sdfghj'
	t db '0123456789ABCDEF' ;用於二進制計算後對應過來找16進制數
	info db 0dh,0ah,'the id of @ is : $'
	count equ $-t1
data ends
stack segment
	db 512 dup(?)
stack ends
code segment
assume cs:code,ds:data,es:data
	start:

	mov ax,data
	mov ds,ax
	mov es,ax

	mov ax,stack
	mov ss,ax

	mov sp,512

	mov dx,offset info ;提示信息
	mov ah,9
	int 21h

	mov al,'@'
	mov di,offset t1 ;取數組t1的首地址到di寄存器中 
	mov cx,count 

	cld  ;clear df    將方向標誌位DF清零 課本20頁 0-up,1-down,一直向右
	repne scasb ;找到與al相同的數就退出掃描   一直重複搜索到t1字符串末尾  課本134 

	;但存在問題:此時,cx沒有減爲0,可是di已經增長1,因此下面須要減1

	;	注意:在掃描時,他是先進行di所在位置的數進行比較,不管相等仍是不想等,他都會自動執行di+1
	dec di ;因爲上面的循環中s進行了自增,相等了跳出,但此時di多加了1,想要的到咱們的數就須要減1
	mov ax,di 

	mov cx,4

	s1:
	push cx
	mov cl,4 ;因爲這裏會改變cx的值,因此在上面須要先將cx入棧進行儲存
	rol ax,cl
	mov si,ax
	and ax,0fh
	mov bx,ax
	mov dl,t[bx]

	mov ah,2
	int 21h

	mov ax,si
	pop cx

	loop s1 ;每次執行完

	add si,2

	mov ah,4ch
	int 21h

code ends
end start
複製代碼

4.冒泡排序

1.jae (cf-進位標誌)

  • 轉移條件:cf=0
  • 用於無符號
  • 大於或等則跳轉

2.cmp

  • cmp eax, ebx (eax - ebx = 03h)
  • 不保存結果,只是根據結果修改相應的標誌位

3.xchg

交換兩個操做數的數據debug

;每一趟冒泡排序都會將最小的浮到最下面
;指向最後一個數,和倒數第二個數進行比較--比較係數在自減
data segment
	t1 db 5,6,1,7,4,3,2
	count equ $-t1
data ends
code segment
assume cs:code,ds:data
start:

	mov ax,data
	mov ds,ax

	mov cx,count 
	dec cx

	bubble:
		push cx

	mov bx,count
	dec bx 

	change:
		mov al,t1[bx]
		cmp al,t1[bx-1]
		jae next ;知足條件 -> next; jae轉移條件:cf=0 	大於等於 -> 轉移 

		xchg al,t1[bx-1] ;不知足條件 (小於)則進行交換
		mov t1[bx],al

	next: 
		dec  bx
		loop change

	pop cx
	loop bubble

	mov ah,4ch
	int 21h

code ends
end start
複製代碼

單步查看每一次排序後的結果3d

初始數據:t1 db 5,6,1,7,4,3,2調試

【注意⚠️】

剛開始進入的是小循環後,就一直t.....t到第二次小循環的loop ,而後再 p dcode

  • 第一次遇到的是小循環,第二次遇到的大循環
相關文章
相關標籤/搜索