- 記錄彙編語言課筆記,可能有不正確的地方,歡迎指出
- 教材《80X86微機原理及接口技術實驗指導書》
- 這篇文章是書中部分軟件實驗代碼的總結,可以用Tdpit 環境編譯並運行在配套實驗箱中(本文中給出的軟件實驗代碼實際上不需要實驗箱的硬件資源),這個環境支持比較標準的intel風格彙編,我估計在masm編譯器中也能便宜運行。
- 下一篇文章將給出一些硬件實驗的示例
- 後面我會發一些基於nasm編譯器的全彙編代碼,nasm也支持intel風格全彙編,但是在語法上稍微有點區別,將來發出來後可以和這裏的代碼對比看
- nasm和masm的區別
一、軟件實驗
- 實驗中所使用DOS 功能調用( INT 21H )說明如下
- 2號功能:顯示單個字符輸出
入口:AH=02H
調用參數:DL= 輸出字符 - 9號功能:顯示字符串
入口:AH=09H
調用參數:DS:DX= 串地址,’$'爲結束字符 - 10號功能:鍵盤輸入
入口:AH=0 A H
調用參數:DS:DX= 輸入緩衝區地址, 首字節爲緩衝區字節長度,第二字節爲實際輸入的字符計數 - 4ch號功能:返回 DOS 系統
入口:AH=4CH
調用參數:AL= 返回碼
- 2號功能:顯示單個字符輸出
1. 四則運算
(1)實驗要求
完成 32 位無符號數的加法、減法,16 位乘以 16 位,32 位除以 16 位除法的四則運算練習。
(2)原理提要
- 字節序
字節序分爲大端模式(Big-Endian)和小端模式(Little-Endian),定義如下:- Little-Endian 就是低位字節排放在內存的低地址端,高位字節排放在內存的高地址端。
- Big-Endian 就是高位字節排放在內存的低地址端,低位字節排放在內存的高地址端。
例如:32bit 寬的數 0x12345678 在小端模式以及大端模式 CPU 內存中的存放方式(假
設從地址 0x4000 開始存放)爲:
- x86架構是小端存儲的,注意下面代碼
A DW 1234H, 5678H ;被加數
,可以看到這一句定義了連續的兩個字數據,數據地址按先後順序由低到高排列,又因爲每一個字在存儲時按找小段存儲規則,所以它在內存中的存儲情況時34 12 78 56
,解釋稱十六進制數就是0x56781234
(3)代碼示例
DATA SEGMENT
A DW 1234H, 5678H ;被加數 32位數分兩個16位存 56781234H
B DW 0FEDCH, 123AH 加數 32位數分兩個16位存 FEDC123AH
C DW 2 DUP (?) ;預留和 留兩個雙字(16位)空間存加法結果
AD DW 0FEDCH, 0BA98H;被減數 BA98FEDCH
BD DW 1234H, 789AH ;減數 789A1234H
CD DW 2 DUP (?) ;預留差
A1 DW 0D678H ;被乘數
B1 DW 0012H ;乘數
C1 DW 2 DUP (?) ;預留積
A2 DW 5678H, 0234H ;被除數 02345678
B2 DW 0F234H ;除數 F234
C2 DW 2 DUP (?) ;預留商,餘數
DATA ENDS
STACK1 SEGMENT STACK
;DB 100 DUP(?)
buffer db 100 dup(0)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1
START PROC FAR
;標準序
PUSH DS
MOV AX, 0
PUSH AX
MOV AX, DATA
MOV DS, AX
;32位+32位 結果68B31110H
MOV AX, A
ADD AX, B
MOV C, AX ;低16位加完存在C,進位在CF
MOV AX, A+2
ADC AX, B+2 ;ADC帶進位加,處理高16位,存在C+2
MOV C+2, AX
;32位-32位 結果41FEECA8H
MOV AX, AD
SUB AX, BD
MOV CD, AX
MOV AX, AD+2
SBB AX, BD+2
MOV CD+2, AX
;16位乘16位 結果000F1470H
MOV AX, A1
MOV BX, B1
MUL BX
MOV C1, AX
MOV C1+2, DX
;32位除16位 結果254H..7568H
MOV DX, A2+2
MOV AX, A2
MOV BX, B2
DIV BX
MOV C2, AX ;商在AX
MOV C2+2, DX ;餘數在DX
RET
START ENDP
CODE ENDS
END START
- 在emu8086中運行並查看內存,可以觀察到計算結果
2. 數據統計
(1)實驗任務
- 本實驗要求通過求某數據區內負數的個數來表現循環程序的結構形式。要求實驗程序在數據段
中存放一組數據,分類統計數據中正數、負數和零的個數,並分別存入內存變量 Positive、Negative
和 Zero 中。將所有數據累加求和,存入 SUM 中。
(2)參考代碼
- 主要邏輯代碼
;宏函數,輸出回車
CRLF MACRO
MOV DL, 0DH
MOV AH, 02H ;INT21的2號功能(單個字符輸出)
INT 21H
MOV DL, 0AH
MOV AH, 02H
INT 21H ;連續輸出0DH和0AH,顯示回車
ENDM
DATA SEGMENT
NUM DB 12H,88H,82H,89H,33H,90H,0H,10H,0BDH,01H ;10個8位數據
Positive DB DUP (0) ;正數個數 4
Negative DB DUP (0) ;負數個數 5
Zero DB DUP (0) ;0個數 1
SUM DW 2 DUP (0) ;總和
MESP DB 'Positive number:$'
MESN DB 'Negative number:$'
MESZ DB 'Zero number:$'
MESS DB 'Sum = $'
result DB 0,0,'$'
DATA ENDS
STACK1 SEGMENT STACK
;DB 100 DUP(?)
buffer db 100 dup(0)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1 ;設置段寄存器
START PROC FAR
PUSH DS
MOV AX, 0
PUSH AX
MOV AX, DATA
MOV DS, AX
MOV CX,10 ;循環10次
LEA SI,NUM
MOV BX,0
LAB1:
MOV DL,[SI]
CMP DL,0 ;判斷num是否爲0
JG LAB2 ;num>0,跳轉到LAB2
JL LAB3 ;num<0,跳轉到LAB3
INC ZERO ;num=0,ZERO加1
JMP LAB4
LAB2:
INC Positive ;負數+1
JMP LAB4
LAB3:
INC Negative ;正數+1
LAB4:
MOV AL,[SI]
CBW ;符號拓展,8位拓展爲16位
ADD SUM,AX ;+sum
ADC [SUM+2],0
INC SI
LOOP LAB1 ;循環
RET
START ENDP
CODE ENDS
END START
-
觀察內存:
-
顯示部分代碼 (利用int 21h的9號功能)
MOV DX,OFFSET MESP ;顯示“Positive number:”提示
MOV AH,9
INT 21H
MOV BL,Positive ;取字節變量positive
MOV AL,BL
SHR AL,4
CALL ToASCII ;把高四位轉換爲對應的ASCII碼
MOV [result],AL
MOV AL,BL
CALL ToASCII ;把低四位轉換爲對應的ASCII碼
MOV [result+1],AL
MOV DX,OFFSET result
MOV AH,9
INT 21H
ToASCII PROC
AND AL,0FH
ADD AL,'0'
CMP AL,'9'
JBE LAB5
ADD AL,7
LAB5:
RET
ToASCII ENDP
3. 代碼轉換
(1)實驗任務
- 從鍵盤輸入小寫字母(最多 20 個),以 “.”號作爲結束標誌, 將其變換成相應的大寫字母輸岀
在屏幕上。
(2)原理提要
-
輸入小寫字母用 INT 21 的 0AH 號功能,將讀入的數據存放在緩衝區 SMALL 中,其中 SMALL
的笫一個字節指岀緩衝區能容納的字節數,不能爲 0(程序暫定爲 50),第二個字節保留,以用作存放
實際鍵入的輸入字符的個數;從笫三個字節開始存放從鍵盤上輸入字符的 ASCII 碼,所以轉換時要
從 SMALL 的笫三個字節,即 SMALL+2 開始。 -
SMALL 中存放的是小寫字母的 ASSII 碼,將此值減去 20H,即爲大寫字母的 ASSII 碼,將其依次
存放在名爲 CAPITAL 的數據段中,然後用 INT 21 中的 09H 功能輸出。
(3)參考代碼
CRLF MACRO
MOV DL, 0DH
MOV AH, 02H ;INT21的2號功能(單個字符輸出)
INT 21H
MOV DL, 0AH
MOV AH, 02H
INT 21H ;連續輸出0DH和0AH,顯示回車
ENDM
DATA SEGMENT
MES1 DB 'PLEASE INPUT THE SMALL LETTER,ENDED WITH ".":$'
MES2 DB 'THE CAPTAL LETTER IS:$'
SMALL DB 50 ; 預留鍵盤輸入緩衝區長度爲50個
DB 0 ; 預留實際鍵盤輸入字符數的個數
DB 50 DUP(0) ; 存放輸入符號串的位置
CAPITAL DB 50 DUP(0) ; 預留大寫字母緩衝區長度爲50個
DATA ENDS
STACK1 SEGMENT STACK
DB 100 DUP (0)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK1
START PROC FAR
PUSH DS
MOV AX, 0
PUSH AX
MOV AX, DATA
MOV DS, AX ;數據段DS指向DATA
MOV AH, 9 ;INT21的9號功能(輸出)
LEA DX, MES1 ;輸出信息位置
INT 21H ;輸岀提示信息MES1
CRLF ;宏調用,輸出回車
MOV AH, 0AH ;INT21的10號功能(輸入)
LEA DX, SMALL ;輸入信息緩存位置
;INC DX
INT 21H ;接收小寫字符串
CRLF ;宏調用,輸出回車
;轉換部分利用INT21的10號功能得到的字符串長度實現,沒有考慮超長問題
;LEA SI,SMALL
;LEA DI,CAPITAL
;XOR CH,CH ;CL中存儲循環次數,注意最後輸入的.不算
;MOV CL,[SI+1]
;ADD SI,2 ;指向真正輸入數據
;DEC CL
;LOOPSIGN: ;循環cx次,把小寫字符轉大寫存入CAPITAL
;MOV AL,[SI]
;SUB AL,20H
;MOV [DI],AL
;INC DI
;INC SI
;LOOP LOOPSIGN
;轉換時利用句號判斷終止時機,進行了長度限制,比上面那個好
LEA BX, SMALL+2
LEA DI, CAPITAL
MOV CX, 20 ;最多20個字符
LAB:
MOV AL, [BX]
CMP AL, 2EH ;是否遇到句號.
JE KE
SUB AL, 20H ;轉爲大寫,ASCLL-20H
MOV [DI], AL
INC BX
INC DI
LOOP LAB
KE:
MOV AL, '$' ;大寫字符串後加“$”
MOV [DI], AL
MOV DX, OFFSET MES2 ;輸岀提示信息MES2
MOV AH, 9
INT 21H
CRLF ;宏調用,輸出回車
MOV DX, OFFSET CAPITAL
MOV AH, 9 ;輸岀大寫字符串
INT 21H
RET
START ENDP
CODE ENDS
END START
- 軟件部分代碼到此結束,下一篇文章給出一些硬件實驗相關的代碼