【實驗三】轉移指令跳轉原理及其簡單應用編程


任務1

task1.asm

assume cs:code, ds:data
data segment
	x    db  1, 9, 3
	len1 equ $ - x  	; 符號常量, $指下一個數據項的偏移地址,這個示例中,是3
	
	y    dw  1, 9, 3
	len2 equ $ - y  	; 符號常量, $指下一個數據項的偏移地址,這個示例中,是9
data ends
code segment
	start:
	      mov  ax, data
	      mov  ds, ax

	      mov  si, offset x	; 取符號x對應的偏移地址0 -> si
	      mov  cx, len1    	; 從符號x開始的連續字節數據項個數 -> cx
	      mov  ah, 2

	s1:   mov  dl, [si]
	      or   dl, 30h		; 數值轉為字符
	      int  21h

	      mov  dl, ' '
	      int  21h         	; 輸出空格

	      inc  si
	      loop s1

	      mov  ah, 2
	      mov  dl, 0ah
	      int  21h         	; 換行
	      
	      mov  si, offset y	; 取符號y對應的偏移地址3 -> si
	      mov  cx, len2/2  	; 從符號y開始的連續字數據項個數 -> cx
	      mov  ah, 2

	s2:   mov  dx, [si]
	      or   dl, 30h
	      int  21h

	      mov  dl, ' '
	      int  21h         	; 輸出空格

	      add  si, 2
	      loop s2
	      
	      mov  ah, 4ch
	      int  21h
code ends
end start

int 21h 功能2:在標准輸出上顯示一個字符並將光標前進一個位置。
接收參數:AH=2
DL=字符值
返回值: 無

image-20211123160740731

  1. 理解運算符offset、偽指令equ、預定義符號$的靈活使用。通過line4、line6,以及數據項的數據屬性(字節、字、雙字,等),可以方便計算出連續數據項的個數,而無需人工計數。
    注*: 符號常量len1, len2不占用數據段內存空間

  2. 回答問題

    ① line26, 匯編指令 loop s1 跳轉時,是根據位移量跳轉的。通過debug反匯編,查看其機器碼,分析其跳轉的位移量是多少?(位移量數值以十進制數值回答)從CPU的角度,說明是如何計算得到跳轉后標號s1其后指令的偏移地址的。

    image-20211123161500421
    E2F2中 位移量: F2(h) --> 11110010(b) --> 00001110(b) --> -12(d) (補碼-->原碼)
    位移量的計算: d(h) - 19(h) --> -12(d)
    CPU根據目標偏移地址減去當前偏移地址得到位移量

    ② line44,匯編指令 loop s2 跳轉時,是根據位移量跳轉的。通過debug反匯編,查看其機器碼,分析其跳轉的位移量是多少?(位移量數值以十進制數值回答)從CPU的角度,說明是如何計算得到跳轉后標號s2其后指令的偏移地址的。

    image-20211123163549842
    分析同上, 跳轉的位移量為 FO(h).

任務2

task2.asm

assume cs:code, ds:data

data segment
    dw 200h, 0h, 230h, 0h
data ends

stack segment
    db 16 dup(0)
stack ends

code segment
start:  
    mov ax, data
    mov ds, ax

    mov word ptr ds:[0], offset s1
    mov word ptr ds:[2], offset s2
    mov ds:[4], cs

    mov ax, stack
    mov ss, ax
    mov sp, 16

    call word ptr ds:[0]
s1: pop ax

    call dword ptr ds:[2]
s2: pop bx
    pop cx

    mov ah, 4ch
    int 21h
code ends
end start

根據call指令的跳轉原理,先從理論上分析,程序執行到退出(line31)之前,寄存器(ax) = ? 寄存器(bx) = ? 寄存器(cx) = ?

分析:
call word ptr ds:[0] 短轉移, 將下一條指令偏移地址(ip)壓入棧, 並轉移至 ds:[0]地址即 s1 處, 此后的 pop ax 將該內容出棧給ax;
call dword ptr ds:[2] 段間轉移, 將下一條指令基址和偏移地址(cs 和 ip)壓入棧, 並轉移至 ds:[2] 起始的雙字指向的地址即 s2 處, 此后的 pop bx 將ip出棧給ax, pop cx 將 cs 出棧給 cx.
即:
ax = s1 bx = s2 cx = s2行所在段基址

image-20211123170907118

image-20211123170024300

任務3

針對8086CPU,已知邏輯段定義如下:

data segment
	x db 99, 72, 85, 63, 89, 97, 55
	len equ $- x
data ends

編寫8086匯編源程序task3.asm,在屏幕上以十進制形式輸出data段中這一組連續的數據,數據和數據之間以空格間隔。
要求:

  • 編寫子程序printNumber
    功能:以十進制形式輸出一個兩位數
    入口參數:寄存器ax(待輸出的數據 --> ax)
    出口參數:無
  • 編寫子程序printSpace
    功能:打印一個空格
    入口參數:無
    出口參數:無
    在主體代碼中,綜合應用尋址方式和循環,調用printNumber和printSpace, 實現題目要求。

task3.asm

assume cs:code, ds:data

data segment
	x	db  99, 72, 85, 63, 89, 97, 55
	len	equ $- x
data ends

code segment
	main:     
		mov ax, data
		mov ds, ax
		
		mov cx, len
		mov si, offset x
	print:
		mov al, [si]
		mov ah, 0
		call printNumber
		call printSpace
		inc si
		loop print

		mov ah, 4ch
		int 21h

	;功能:以十進制形式輸出一個兩位數
	;入口參數:寄存器ax(待輸出的數據 --> ax)
	;出口參數:無
	printNumber:
		mov bl, 10
		div bl
		mov bx, ax
		
		mov ah, 2

		mov dl, bl	; 打印商(10位)
		or dl, 30h
		int 21h

		mov dl, bh	; 打印余數(個位)
		or dl, 30h
		int 21h
		ret
             
	printSpace:
		mov ah, 2
		mov dl, ' '
		int 21h
		ret

code ends
end main

運行結果:

image-20211124185325749

任務4

針對8086CPU,已知邏輯段定義如下:

data segment
	str db 'try'
	len equ $ - str
data ends

編寫8086匯編源程序task4.asm,在屏幕上以指定顏色、指定行,在屏幕上輸出字符串。
要求:

  • 編寫子程序printStr
    • 功能:在指定行、以指定顏色,在屏幕上顯示字符串
    • 入口參數
      • 字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si)
      • 字符串長度 --> cx
      • 字符串顏色 --> bl
      • 指定行 --> bh (取值:0 ~24)
    • 出口參數:無
  • 在主體代碼中,兩次調用printStr,使得在屏幕最上方以黑底綠字顯示字符串,在屏幕最下方以黑
    底紅色顯示字符串

task4.asm

assume cs:code
data segment
	str db	'try'
	len equ	$ - str
data ends
code segment
	main:
		mov ax, 0b800h
		mov es, ax
	
	first_print:
		mov ax, data
		mov ds, ax
		mov si, offset str
		mov cx, len
		mov bl, 00000010b	; 黑底綠字
		mov bh, 0			; 第0行
		call printStr
	
	second_print:
		mov si, offset str
		mov cx, len
		mov bl, 00000100b	; 黑底紅字
		mov bh, 24			; 第24行
		call printStr
	
		mov ah, 4ch
		int 21h

	; 入口參數:
  	;	字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si)
  	;	字符串長度 --> cx
  	;	字符串顏色 --> bl
  	;	指定行 --> bh (取值:0 ~24)
	printStr:
		push bp						; 因為要用到bp和di, 先保存現場
		push di

		mov ah, 0
		mov al, 160
		mul bh					
		mov bp, ax					; 計算行數偏移地址存儲在bp
		mov di, si					; di存儲顯存中每個字符偏移地址
		printChar:
			mov al, ds:[si]
			mov es:[bp+di], al		; 字符
			mov es:[bp+di+1], bl	; 顏色
			inc si
			inc di
			inc di					; di要加兩次
			loop printChar
		
		pop bp						; 還原現場
		pop di
		ret 

code ends
end main

運行結果:

image-20211124201416292

任務5

針對8086CPU,針對8086CPU,已知邏輯段定義如下:

data segment
	stu_no db '20498329042'
	len = $ - stu_no
data ends

在80×25彩色字符模式下,在屏幕最后一行正中間顯示學號。要求輸出窗口藍底,學號和兩側折線,以
白色前景色顯示。

task5.asm

assume cs:code, ds:data
data segment
	stu_no db '201983300514'
	len = $ - stu_no
data ends

code segment
	main:
		call print_blue_screen
		call print_stu_no

		mov ah, 4ch
		int 21h

	print_blue_screen:
		push ax		; 保存現場
		push es
		push si

		mov ax, 0b800h
		mov es, ax
		mov cx, 2000
		mov si, 1
		single_blue:
			mov byte ptr es:[si], 00010000b
			inc si
			inc si
			loop single_blue
		
		pop si		; 還原現場
		pop es
		pop ax		
	ret
	
	print_stu_no:
		push ax		
		push es
		push si
		push ds
		push di
	prefix:
		mov ax, 0b800h
		mov es, ax
		mov cx, 34
		mov si, 3840	; si存放每次顯存輸出的偏移地址
		call print_dash
	content:
		mov ax, data
		mov ds, ax
		mov cx, len
		mov di, 0		; di存放data中每個字符的偏移地址
		single_no:
			mov al, ds:[di]
			inc di
			mov byte ptr es:[si], al 
			inc si
			mov byte ptr es:[si], 00010111b
			inc si
			loop single_no
	postfix:
		mov cx, 34
		call print_dash
		
		pop di
		pop ds
		pop si
		pop es
		pop ax
	ret
	
	; 輸入參數:
	;	顯示的基地址si
	;	輸出長度cx
	; 輸出:
	;	迭代后的基地址si
	print_dash:
		single_dash:
			mov byte ptr es:[si], '-'
			inc si
			mov byte ptr es:[si], 00010111b
			inc si
			loop single_dash
	ret

code ends
end main

運行結果:

image-20211124214509454


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM