1. 程式人生 > 其它 >C++筆記5-函式/指標/結構體

C++筆記5-函式/指標/結構體

一、實驗目的 1. 理解80×25彩色字元模式顯示原理 2. 理解轉移指令jmp, loop, jcxz的跳轉原理,掌握使用其實現分支和迴圈的用法 3. 理解轉移指令call, ret, retf的跳轉原理,掌握組合使用call和ret/retf編寫彙編子程式的方法,掌握 引數傳遞方式 4. 理解標誌暫存器的作用 5. 理解條件轉移指令je, jz, ja, jb, jg, jl等的跳轉原理,掌握組合使用匯編指令cmp和條件轉移指令實 現分支和迴圈的用法 6. 瞭解在visual studio/Xcode等環境或利用gcc命令列引數反彙編c語言程式的方法,理解編譯器生成 的反彙編程式碼 7. 綜合應用定址方式和彙編指令完成應用程式設計 二、實驗準備 實驗前,請複習/學習教材以下內容: 第9章 轉移指令的原理 第10章 call和ret指令 第11章 標誌暫存器 1. 實驗任務1 教材「實驗9 根據材料程式設計」(P187-189) 程式設計:在螢幕中間分別顯示綠色、綠底紅色、白底藍色的字串'welcome to masm!'。 首先分析: 80*25的彩色字元模式,要輸出三行在中間,所以行資訊應該定為第11行開始,通過老師所給的偏移地址表格 可得11行的偏移地址為1760(十進位制),再看列資訊,需要輸出的字串應占32個位元組,一行160個位元組,所以要在 螢幕中央輸出的話列資訊應該為(160-32)/2=64加上剛才的1760為1824轉換為十六進位制應該為720h,所以給初始的ax 暫存器設定了B872h 程式碼如下:
assume cs:code, ds:data
data segment
    db 'welcome to masm!'
    db 00000010B              ;黑底綠字
    db 00100100B              ;綠底紅字
    db 01110001B              ;白底藍字
data ends

code segment
start:  
     mov ax,data
     mov ds,ax       ;ds指向字串位置

     mov ax,0B872h
     mov es,ax       ;es指向初始行列位置
    
     mov cx,3        ;設定外層3次迴圈
     mov bx,16       ;儲存外層迴圈次數

external: push cx
     mov di,0        ;儲存內層迴圈次數
     mov si,0        ;儲存行列資訊
     
     mov cx,16     ;設定內層16次迴圈  
internal: mov al,ds:[di]     ;低位位元組存放字元資訊
     mov ah,ds:[bx]     ;高位位元組存放顏色資訊
     mov es:[si],ax             ;將字元和顏色資訊移至需要的視訊記憶體區
     
     inc si
     inc si      ;向後推進2個位元組
     inc di     ;向後推進一個字元
     loop internal

     pop cx
     mov ax,es
     add ax,00ah              
     mov es,ax
     inc bx        ;資料段向後推進一個字元來改變顏色資訊
     loop external
    
     mov ax,4c00h
     int 21h
code ends
end start
注意在最後的部分mov ax,es add ax,00ah, mov es ax這部分一定要這樣寫否則會報非法使用暫存器 執行結果如下:

2. 實驗任務2 編寫子程式printStr,實現以指定顏色在螢幕上輸出字串。呼叫它,完成字串輸出。 子程式printSar 功能:以指定顏色在螢幕上(從螢幕左上角開始)輸出字串 要求:字串以0結尾 入口引數 字串的起始地址—> ds: si (其中,字串所在段的段地址—> ds, 字串起始地址 的偏移地址—> si 字串顏色—> al 出口引數:無 使用任意文字編輯器,錄入彙編源程式task2.asm。
assume cs:code, ds:data
data segment
    str db 'try', 0
data ends

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

	mov si, offset str
	mov al, 2
	call printStr

	mov ah, 4ch
	int 21h

printStr:
	push bx
	push cx
	push si
	push di

	mov bx, 0b800H
	mov es, bx
	mov di, 0
s:      mov cl, [si]
	mov ch, 0
	jcxz over
	mov ch, al
	mov es:[di], cx
	inc si
	add di, 2
	jmp s

over:   pop di
	pop si
	pop cx
	pop bx
	ret

code ends
end start
彙編、執行程式,觀察執行結果。 對源程式做如下修改: 把line3改為: 把line12改為: 再次彙編、執行程式,觀察執行結果。 (1)line19-22, line36-39,這組對稱使用的push、pop,這樣用的目的是什麼? 暫存對應暫存器的內容以便於子程式執行完畢後進行恢復。 (2)line30的功能是什麼? 將字元和對應的顏色資訊儲存到視訊記憶體中。 3. 實驗任務3 使用任意文字編輯器,錄入彙編源程式task3.asm。 子程式num2str: 功能:把0~2559之間的任意整數轉換成數字字串,例如,把1984轉換成'1984' 入口引數 要轉換的整數 —> ax 數字字串的起始地址 —> ds:di (其中:數字字串所在段的段地址—> ds,字串 起始地址的偏移地址—>di) 出口引數:無
assume cs:code, ds:data
data segment
        x dw 1984
        str db 16 dup(0)
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov ax, x
        mov di, offset str
        call num2str

        mov ah, 4ch
        int 21h

num2str:
        push ax
        push bx
        push cx
        push dx
        
        mov cx, 0
        mov bl, 10
s1:      
        div bl
        inc cx
        mov dl, ah
        push dx
        mov ah, 0
        cmp al, 0
        jne s1
s2:        
        pop dx
        or dl, 30h
        mov [di], dl
        inc di
        loop s2
        
        pop dx
        pop cx
        pop bx
        pop ax

        ret
code ends
end start
閱讀原始碼,理解子程式num2str的彙編實現。 子任務1 對task3.asm進行彙編、連結,得到可執行程式後,在debug中使用u命令反彙編,使用g命令執行 到line15(程式退出之前),使用d命令檢視資料段內容,觀察是否把轉換後的數字字串'1984'存放 在資料段中str標號後面的單元。 子任務2 對task3.asm原始碼進行修改、完善,把task2.asm中用於輸出以0結尾的字串的子程式加進來, 實現對轉換後的字串進行輸出。
assume cs:code, ds:data
data segment
        x dw 1984
        str db 16 dup(0)
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov ax, x
        mov di, offset str
        mov si,0
        call num2str

        mov ah, 4ch
        int 21h

num2str:
        push ax
        push bx
        push cx
        push dx
        
        mov cx, 0
        mov bl, 10
s1:      
        div bl
        inc cx
        mov dl, ah
        push dx
        mov ah, 0
        cmp al, 0
        jne s1
s2:        
        pop dx
        or dl, 30h
        mov [di], dl
        mov dh,2
        mov bx,0b800H
        mov es,bx
        mov es:[si],dx
        inc si
        inc si
        inc di
        loop s2
        
        pop dx
        pop cx
        pop bx
        pop ax

        ret
code ends
end start
把task3.asm原始碼中,line3中整數改成0~2559之間的任意數值,執行測試,觀察結果。 改成1324: 4. 實驗任務4 使用任意文字編輯器,錄入彙編源程式task4.asm。
assume cs:code, ds:data
data segment
        str db 80 dup(?)
data ends

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

s1:        
        mov ah, 1
        int 21h
        mov [si], al
        cmp al, '#'
        je next
        inc si
        jmp s1
next:
        mov cx, si
        mov si, 0
s2:     mov ah, 2
        mov dl, [si]
        int 21h
        inc si
        loop s2

        mov ah, 4ch
        int 21h
code ends
end start
彙編、連結、執行程式,輸入一個字串並以#結束(比如,2020, bye#)觀察執行結果。結合執行結 果,理解程式功能,瞭解軟中斷指令。具體地: line12-19實現的功能是? 利用int 21h的1號子功能來實現若輸入的不是#則入棧操作。 line21-27實現的功能是? 利用int 21h的2號子功能來實現輸出剛才入棧的內容 5. 實驗任務5 在visual studio整合環境中,編寫一個簡單的包含有函式呼叫的c程式。程式碼如下: 在line7, line13分別設定斷點,在除錯模式下,檢視反彙編程式碼。 分析反彙編程式碼,從彙編的角度,觀察高階語言中引數傳遞和返回值是通過什麼實現的,以及,引數入 棧順序,返回值的帶回方式,等等。

高階語言的引數傳遞是通過暫存器實現的,這裡可以看到b先入棧然後是a,所以是從右往左入棧,通過call命令呼叫sum函式

這是通過訪問x和y的記憶體資料實現相加的操作將結果存放在ax中返回主函式