title: 匯編求和實驗
keywords: 匯編
tags: [匯編]
categories: 嵌入式
匯編求和實驗
剛開始學習匯編 給大家做個參考
實驗 5 子程序 5.1 實驗目的 ①掌握利用堆棧傳遞參數的子程序調用方法。 ②過程調用偽指令:PROC,ENDP,NEAR和FAR。 ③8088指令:CALL,RET,RETn。 5.2 實驗類型 驗證型實驗\2. 操作步驟 ①輸入,編譯并運行程序。 ②用emu8086運行此程序,觀察并記錄每次過程調用及進出棧指令前后的SP和堆棧內容。 ③記錄最后結果:SUM1,SUM2的段及偏移地址和它們的內容。 ④修改并自編程序,使得在屏幕上可以輸入任意6個十進制數字,同時在屏幕上輸出SUM1 的結果(要求輸出十進制數字,打印出有效2位數即可)。
-
AX
:這是一個通用寄存器,通常用于算術和邏輯操作。在這段程序中,它被用來存儲DATAS
段的地址,然后這個地址被移動到DS
寄存器。 -
DS
:這是一個段寄存器,用于存儲數據段的地址。在這段程序中,它被設置為DATAS
段的地址,這樣程序就可以訪問在DATAS
段中定義的數據了。 -
SI
:這是一個索引寄存器,通常用于存儲數組或字符串的索引。在這段程序中,它被用來存儲DATA
數組的當前索引。 -
CX
:這是一個計數寄存器,通常用于存儲循環的次數。在這段程序中,它被設置為6,表示輸入循環的次數。 -
DX
:這是一個通用寄存器,通常用于I/O操作。在這段程序中,它被用來存儲字符串的地址,然后這個地址被用于INT 21H
中斷,以打印字符串。 -
AH
:這是AX
寄存器的高8位,通常用于存儲操作碼。在這段程序中,它被設置為9,表示打印字符串的操作。 -
DI
:這是一個索引寄存器,通常用于存儲數組或字符串的索引。在這段程序中,它被初始化為0,用于打印總和。修改并自編程序,使得在屏幕上可以輸入任意6個十進制數字,同時在屏幕上輸出SUM1 的結果(要求輸出十進制數字,打印出有效2位數即可)。
DATAS SEGMENTstring_1 DB 'input','$' ; 提示輸入string_2 DB 'input again','$' ; 無效輸入的錯誤消息string_3 DB ' ','$' ; 空格字符DATA DW 10 DUP(?) ; 存儲輸入數字的數組message DB 0ah,'sum:',0DH,'$' ; 總和輸出的消息
DATAS ENDSSTACKS SEGMENTDW 256 dup(?)
STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATAS,SS:STACKSSTART:MOV AX,DATASMOV DS,AX ; 設置DS寄存器指向DATAS段MOV SI, 0 ; 指針初始化MOV CX, 6 ; 循環次數MOV DX, OFFSET string_1 ; 提示輸入MOV AH, 9INT 21HLp:CALL Input ; 調用輸入子程序ADD SI, 2 ; 指針增加2(每個輸入數字占2個字節)Loop Lp ; 循環直到所有數字輸入完畢MOV DX, OFFSET message ; 打印總和消息MOV AH, 9INT 21HCALL Get_sum ; 調用Get_sum子程序計算總和MOV DX, AXADD DX, 30HMOV AH, 2INT 21HMOV AH, 4CH INT 21HInput PROC Nearpush AX push BXpush CX push DX MOV BX, 0 CLC ; 清除進位標志MOV DX, 0 Lp_0:MOV AH, 1INT 21H ; 從輸入中讀取一個字符CMP AL, 20H ; 檢查輸入是否為空格字符JE L_CRLF ; 如果是空格,跳轉到L_CRLFSUB AL, 30H ; 將ASCII轉換為整數MOV AH, 0 ; 清除AH寄存器XCHG AX, BX ; 交換AX和BX寄存器JMP Lp_0 ; 繼續輸入循環L_CRLF: ; 輸入結束標記(換行)MOV DX, 0MOV DATA[SI], BX ; 將輸入數字存儲在DATA數組中POP DXPOP CXPOP BXPOP AXRET
Input ENDPGet_sum PROC NEARPUSH BXPUSH CXMOV BX, 0MOV CX , 6MOV DI, 0LOP1:MOV AX, DATA[DI]ADD BX, AXADD DI , 2LOOP LOP1MOV AX, BXPOP BXPOP CXRET
Get_sum ENDPCODES ENDS
END START
Input
過程是一個子程序,用于讀取用戶的輸入。它首先將AX、BX、CX和DX寄存器的值壓入堆棧以保存它們的當前狀態。然后,它使用DOS中斷21H的功能1來讀取用戶的輸入。如果輸入是空格(ASCII值為20H),則結束輸入;否則,將輸入的ASCII值轉換為數字,并存儲在BX寄存器中。最后,將BX寄存器的值存儲在DATA
數組中,并恢復AX、BX、CX和DX寄存器的值。
Get_sum
過程是另一個子程序,用于計算DATA
數組中的所有數字的和。它首先將BX和CX寄存器的值壓入堆棧以保存它們的當前狀態。然后,它初始化BX寄存器為0,用于存儲和;初始化CX寄存器為6,表示要加的數字的數量;初始化DI寄存器為0,表示數組的索引。然后,它在循環中將DATA
數組中的每個數字加到BX寄存器中。最后,將和存儲在AX寄存器中,并恢復BX和CX寄存器的值。
但這個有致命缺點
笑死了 直接加0x30得到十進制數字就是 只有0-9可以正常輸出結果
首先,它將12賦值給AX寄存器,然后將10賦值給CL寄存器。然后,它使用div cl
指令將AX寄存器的值除以CL寄存器的值。在這個操作后,商(也就是十位數)存儲在AL寄存器中,余數(也就是個位數)存儲在AH寄存器中。然后,它將AH寄存器的值復制到BH寄存器中。
然后,它檢查AL寄存器的值是否為0。如果AL寄存器的值為0,那么它將跳轉到tito
標簽,否則,它將繼續執行。
接下來,它將AL寄存器的值復制到DL寄存器中,然后將DL寄存器的值增加30H(因為在ASCII編碼中,數字字符的編碼是從30H開始的)。然后,它將AH寄存器的值設置為2,然后調用DOS中斷21H的功能2,將DL寄存器中的字符輸出。
在tito
標簽處,它將BH寄存器的值復制到DH寄存器中,然后將DH寄存器的值增加30H。然后,它將AH寄存器的值設置為2,然后調用DOS中斷21H的功能2,將DH寄存器中的字符輸出。
DATAS SEGMENTstring_1 DB 'input','$' ; 提示輸入string_2 DB 'input again','$' ; 無效輸入的錯誤消息string_3 DB ' ','$' ; 空格字符DATA DW 6 DUP(?) ; 存儲輸入數字的數組message DB 'sum:',0ah,'$' ; 總和輸出的消息
DATAS ENDSSTACKS SEGMENTDW 256 dup(?)
STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATAS,SS:STACKSSTART:MOV AX,DATASMOV DS,AX ; 設置DS寄存器指向DATAS段MOV SI, 0 ; 指針初始化MOV CX, 6 ; 循環次數MOV DX, OFFSET string_1 ; 提示輸入MOV AH, 9INT 21HLp:CALL Input ; 調用輸入子程序ADD SI, 2 ; 指針增加2(每個輸入數字占2個字節)Loop Lp ; 循環直到所有數字輸入完畢MOV DX, OFFSET message ; 打印總和消息MOV AH, 9INT 21HCALL Get_sum ; 調用Get_sum子程序計算總和存到axmov cl, 10div cl mov bh,ah cmp al, 0je tito ;十位為零 跳轉titoMOV Dl, al ADD dl, 30HMOV AH, 2INT 21H tito:MOV Dl, bh ADD dl, 30HMOV AH, 2INT 21H Input PROC Nearpush AX push BXpush CX push DX MOV BX, 0 CLC ; 清除進位標志MOV DX, 0 Lp_0:MOV AH, 1INT 21H ; 從輸入中讀取一個字符CMP AL, 20H ; 檢查輸入是否為空格字符JE L_CRLF ; 如果是空格,跳轉到L_CRLFSUB AL, 30H ; 將ASCII轉換為整數MOV AH, 0 ; 清除AH寄存器XCHG AX, BX ; 交換AX和BX寄存器JMP Lp_0 ; 繼續輸入循環L_CRLF: ; 輸入結束標記(換行)MOV DX, 0MOV DATA[SI], BX ; 將輸入數字存儲在DATA數組中POP DXPOP CXPOP BXPOP AXRET
Input ENDPGet_sum PROC NEARPUSH BXPUSH CXMOV BX, 0MOV CX , 6MOV DI, 0LOP1:MOV AX, DATA[DI]ADD BX, AXADD DI , 2LOOP LOP1MOV AX, BXPOP BXPOP CXRET
Get_sum ENDPCODES ENDS
END START
如此我們便完成這節課的任務了