50行程式碼完成視訊通話 (WebRTC + WebSocket)
------------恢復內容開始------------
實驗任務一:
1 assume cs:code, ds:data, ss:stack 2 3 data segment 4 db 'welcome to masm!' 5 db 2h,24h,71h ;三行文字的顏色 6 data ends 7 8 stack segment 9 db 16 dup (0) 10 stack ends 11 12 code segment 13 start: 14 mov ax,data 15 mov ds,ax ;程式碼段的段始址送到ds 16 17 mov ax,stack 18 mov ss,ax 19 mov sp,16 ;棧段的棧頂指標指向ss:16 20 21 mov ax,0B87Ch ;將字串顯示在螢幕中間的位置 22 mov es,ax 23 24 mov cx,3 ;三行的顯示程式碼是外層迴圈三次 25 mov bx,0 ;記錄當前是第幾行,也是外層迴圈的次數 26 27 s: pushcx 28 mov cx,16 ;每行顯示16個字元,記憶體迴圈16次 29 mov di,0 ;記錄記憶體迴圈的次數 30 31 s0: mov al,ds:[di] ;低位元組顯示文字 32 mov ah,ds:[bx+16] ;高位元組顯示顏色屬性 33 mov si,di 34 add si,si 35 mov es:[si],ax 36 inc di 37 loop s0 38 39 popcx 40 mov ax,es 41 add ax,00ah ;切換到下一行的位置 42 mov es,ax 43 inc bx 44 loop s 45 46 mov ax,4c00h 47 int 21h 48 code ends 49 end start
執行結果為:
在一頁顯示緩衝區中:
偏移000~09F對應顯示器上的第1行(80個字元佔160個位元組);
偏移0A0~13F對應顯示器上的第2行;
偏移140~1DF對應顯示器上的第3行;
以此類推,可知偏移780~81F對應顯示器上的第12行。
在一行中,一個字元佔兩個位元組的儲存空間(一個字),低位位元組儲存字元的ASCLL碼,高位位元組儲存字元的屬性。一行共有80個字元,佔160個位元組。
即在一行中:
00~01單元對應顯示器上的第1列;
02~03單元對應顯示器上的第2列;
04~05單元對應顯示器上的第3列;
依此類推,可知,40~41單元對應顯示器上的第30列。
因此字串首地址設為:B878*16+40=B87Ch
黑底綠字,屬性位元組為:00000010
綠底紅字,屬性位元組為:00100100
白底藍字,屬性位元組為:01110001
注意:在顯示緩衝區中,偶地址存放字元,奇地址存放字元的顏色屬性
實驗任務二:
1 assume cs:code, ds:data 2 data segment 3 str db 'another try', 0 ;定義以0結尾的字串try 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 11 mov si, offset str ;offset操作符取得了str的偏移地址0 12 mov al, 4 13 call printStr ;跳轉指令,跳轉到printStr處執行 14 15 mov ah, 4ch 16 int 21h 17 18 printStr: 19 push bx ;將暫存器壓入棧,子程式中可能會用到這些暫存器 20 push cx 21 push si 22 push di 23 24 mov bx, 0b800H 25 mov es, bx 26 mov di, 0 27 s: mov cl, [si] 28 mov ch, 0 29 jcxz over ;cx為0時,指令跳轉到over處執行 30 mov ch, al 31 mov es:[di], cx 32 inc si 33 add di, 2 34 jmp s 35 36 over: pop di ;將暫存器出棧,恢復暫存器原先的值 37 pop si 38 pop cx 39 pop bx 40 ret 41 42 code ends 43 end start
執行結果為:
對源程式做如下修改: 把line3改為:str db 'another try', 0把line12改為:mov al, 4 彙編,連結,觀察執行結果為: 基於執行結果,理解原始碼,以及,組合使用轉移指令call和ret實現子程式的原理與方法。具體地,在line18-40中: line19-22, line36-39,這組對稱使用的push、pop,這樣用的目的是什麼? 答:由於暫存器數量有限,子程式中可能會使用到這些暫存器,但是我們不確定這些暫存器中是否儲存了重要的資訊,因此先將暫存器bx,cx,si,di壓入棧,在子程式中就可以隨意使用這些暫存器,子程式執行完畢,將暫存器出棧,出棧的同時暫存器也會恢復原來的值。 line30的功能是什麼? 答:line 30行的內容是mov ch, al,在line 12中有一條指令mov al, 4,這兩條指令表示將4送入到ch中,根據之前的實驗可知,高位位元組存放的是資料的顏色屬性,因此line 30行的功能是改變資料的顏色屬性。 實驗任務三:
1 assume cs:code, ds:data 2 data segment 3 x dw 1984 ;定義x為一個字變數賦初值為1984 4 str db 16 dup(0) ;定義str為一個byte陣列,存放16個位元組的0 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov ax, x 12 mov di, offset str 13 call num2str 14 15 mov ah, 4ch 16 int 21h 17 18 num2str: 19 push ax 20 push bx 21 push cx 22 push dx 23 24 mov cx, 0 25 mov bl, 10 26 s1: 27 div bl 28 inc cx 29 mov dl, ah 30 push dx 31 mov ah, 0 32 cmp al, 0 33 jne s1 34 s2: 35 pop dx 36 or dl, 30h 37 mov [di], dl 38 inc di 39 loop s2 40 41 pop dx 42 pop cx 43 pop bx 44 pop ax 45 46 ret 47 code ends 48 end start
子任務一:
彙編,連結之後對該程式用u命令進行反彙編,用g命令執行到mov ah,4ch,用d命令檢視執行之後的結果,發現把轉換後的數字字串'1984'存放在資料段中str標號後面的單元。
子任務二:
1 assume cs:code, ds:data 2 data segment 3 x dw 1984 ;定義x為一個字變數賦初值為1984 4 str db 16 dup(0) ;定義str為一個byte陣列,存放16個位元組的0 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov ax, x 12 mov di, offset str 13 call num2str 14 mov si, offset str 15 call printStr 16 17 mov ah, 4ch 18 int 21h 19 20 num2str: 21 push ax 22 push bx 23 push cx 24 push dx 25 26 mov cx, 0 27 mov bl, 10 28 s1: 29 div bl 30 inc cx 31 mov dl, ah 32 push dx 33 mov ah, 0 34 cmp al, 0 35 jne s1 36 s2: 37 pop dx 38 or dl, 30h 39 mov [di], dl 40 inc di 41 loop s2 42 43 pop dx 44 pop cx 45 pop bx 46 pop ax 47 48 ret 49 50 printStr: 51 push bx 52 push cx 53 push si 54 push di 55 56 mov bx, 0b800H 57 mov es, bx 58 mov di, 0 59 s: 60 mov cl, [si] 61 mov ch, 0 62 jcxz over 63 mov ch, al 64 mov es:[di], cx 65 inc si 66 add di, 2 67 jmp s 68 69 over: pop di 70 pop si 71 pop cx 72 pop bx 73 ret 74 code ends 75 end start
執行結果為:
將line3中的整數改為1234,彙編,連結,執行結果為:
將line3中的整數改為2020,彙編,連結,執行結果為:
通過實驗發現,修改數字之後,輸出的字元顏色及屬性都不相同。
實驗任務四:
1 assume cs:code, ds:data 2 data segment 3 str db 80 dup(?) 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 mov si, 0 11 12 s1: 13 mov ah, 1 14 int 21h 15 mov [si], al 16 cmp al, '#' 17 je next 18 inc si 19 jmp s1 20 next: 21 mov cx, si 22 mov si, 0 23 s2: mov ah, 2 24 mov dl, [si] 25 int 21h 26 inc si 27 loop s2 28 29 mov ah, 4ch 30 int 21h 31 code ends 32 end start
執行結果為:
彙編、連結、執行程式,輸入一個字串並以#結束(比如,2020, bye#)觀察執行結果。結合執行結 果,理解程式功能,瞭解軟中斷指令。具體地: line12-19實現的功能是? 答:迴圈執行將輸入的單個字元寫入記憶體單元中,遇到#跳轉到next處執行。 line21-27實現的功能是? 答:迴圈執行輸出單個字元。 實驗內容五:通過斷點設定,檢視反彙編程式碼,發現在c=sum(a,b)處的彙編指令先將b移到eax暫存器中,將eax壓棧,將a移到ecx暫存器中,將ecx壓棧,接著跳轉到048116Dh處執行,並將此時的add esp,8的偏移地址壓棧,被調函式也可以使用eax、edx、ecx這三個暫存器,所以規定呼叫者需儲存eax、edx和ecx,在從被調函式返回後先恢復這三個暫存器的值再繼續;被呼叫者儲存ebx、esi和edi這三個暫存器,對他們進行壓棧處理,執行完之後,進行出棧操作,遇到ret指令時,繼續回到call指令的下一條指令執行。
------------恢復內容結束------------