匯編運行過程
准備
由於大多數win10
系統都是64
位系統,所以如果直接用link.exe
和masm.exe
來運行asm
文件是不可以的。
所以需要安裝DOSBox
DOSBox,Link,Masm介紹
Link和masm
masm32包即可以支持開發在DOS操作系統下運行的16位應用程序,也可以開發在Windows操作系統下運行的32位應用程序。
masm.exe
——匯編器。我們編寫的源代碼文件就是通過它來匯編生成中間代碼文件,即通常擴展名為.obj的文件。
link16.exe
——連接器。由masm.exe
匯編生成的.obj
文件還不能直接上機運行,必須通過連接器link16.exe
將其連接制作成擴展名為.exe
(或者.com
)的可執行文件才能上機。
但是我們主流的系統基本都是64位了,所以需要用DOSBox
來給我們提供一個16位的DOS
系統環境
DOSBox
在現在的系統下模擬DOS環境的一個工具!是為了運行以前純DOS環境下的軟件而開發的!當然主要用途是運行原來的那些只能在DOS下玩的老游戲!
使用方法:
- 將存放masm、link和源程序文件的文件夾拷貝到某一目錄下,比如c:\examples
- 然后將這個目錄掛為DOSBox的一個盤符下,掛載命令為
Mount c c:\examples
; 可以理解為把當前工作目錄切換到c:\examples
這里,即c:\examples
就是你以后的C:
- 再切換到掛載的c盤:
c:
; 切換到工作目錄
開始寫程序
此次用到的文件
仔細對應DOSBox圖片里面的代碼和這個圖片里面的文件
利用masm.exe生成.OBJ文件
在后綴名為.asm
的文件中,編寫完代碼之后
在DOSBox
中利用masm.exe
運行.asm
文件
masm yourfile.asm ; 注意,可以不加.asm后綴.不加的時候要保持名字不重復
利用link.exe運行.OBJ文件,生成.exe文件
在DOSBox
中利用link.exe
運行.OBJ
文件,然后生成.exe
文件
link yourfile.OBJ ; 注意,可以不加.OBJ后綴.不加的時候要保持名字不重復
這里有warning L4021是因為我在寫代碼的時候沒有定義堆棧區,但是沒有關系
系統自動會幫我們建立堆棧區
運行.exe文件
在DOSBox
中直接運行.exe
文件.OBJ
文件,然后生成.exe
文件
本次的代碼
DATA SEGMENT ;定義數據段
STRING1 DB 'IT IS ODD!','$'
STRING2 DB 'IT IS EVEN!','$'
DATA ENDS
CODE SEGMENT ;定義代碼段
ASSUME CS:CODE,DS:DATA ;ASSUME偽指令,說明段與段寄存器之間的對應關系
START:
MOV AX,DATA ;實現段與段寄存器之間的對應關系,代碼段系統會默認
MOV DS,AX
MOV AH,01H ;調用1號DOS功能,從鍵盤上讀入一個字符,並將該字符回顯在屏幕上
INT 21H
CLC
RCR AL,1
JNC EVN
MOV DX,OFFSET STRING1 ;將字符串Sting1的偏移地址賦給DX
CALL DISPMESS
EVN: MOV DX,OFFSET STRING2
CALL DISPMESS
DISPMESS PROC ;定義一個過程,用於輸出字符串
MOV AH,9 ;調用9號子功能
INT 21H ;返回DOS
MOV AH,4CH ;結束程序
INT 21H
DISPMESS ENDP
CODE ENDS
END START
大作業
USE16的作用
這句指的是,數據段采取16位來存取數據段中的數據。如果use32則是指用32位來存取數據段中的數據。具體的16還是32,根據你編程面向的cpu類型是16位的還是32位的。
另外再補充一點點吧。
cpu將內部存儲單元分成許多邏輯段(Segment),這樣,一個存儲單元除具有一個唯一的物理地址外,還具有多個邏輯地址。
data segment 指的就是數據段。
數據段存放運行程序所用的數據。數據段寄存器DS存放數據段的段地址。各種主存尋址方式(有效地址EA)得到存儲器中操作數的偏移地址。處理器利用DS:EA存取數據段中的數據。
DATA SEGMENT
MESG1 DB 'USERNAME:',0DH,0AH,'$' ;指定用戶名存放的數據區
MESG2 DB 0DH,0AH,'PASSWORD:',0DH,0AH,'$' ;指定密碼的數據區
MESG3 DB 0DH,0AH,0DH,0AH,'Password Right!',0DH,0AH,'$' ;密碼正確提示
MESG4 DB 0DH,0AH,0DH,0AH,'USERNAME Error!',0DH,0AH,'$'; ;用戶名報錯
MESG5 DB 0DH,0AH,0DH,0AH,'Password Error!',0DH,0AH,'$'; ;密碼報錯
BUF1 DB '2018633007'
USERLEN EQU $-BUF1 ;統計用戶名長度
BUF2 DB '5201314'
PWLEN EQU $-BUF2 ;統計密碼長度
BUF3 DB 15 ;用戶輸入用戶名的數據區
DB ?
DB 15 DUP(?)
BUF4 DB 15 DUP(?) ;用戶輸入密碼的數據區
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV AH,9
MOV DX,OFFSET MESG1 ;顯示用戶名輸入界面
INT 21H
MOV AH,0AH
MOV DX,OFFSET BUF3 ;鍵入用戶名字符串
INT 21H
MOV BX,OFFSET BUF1 ;獲得儲存正確賬戶名的偏移地址
MOV SI,OFFSET BUF3+2 ;獲得儲存輸入賬戶名的偏移地址
MOV CX,USERLEN
CMPUSER:
; 進行用戶名對比
MOV AL,[BX]
CMP [SI],AL ;將輸入字符串的對應位置與正確賬戶名進行比較
JNZ ERROR1 ;當前位置和原本的用戶名不一樣就報錯
INC SI
INC BX
LOOP CMPUSER ;重復進行直到字符串結束
MOV AH,9
MOV DX,OFFSET MESG2 ;顯示密碼輸入界面
INT 21H
MOV CX,PWLEN ; 將正確的密碼長度讀入
MOV SI,OFFSET BUF4 ;獲得儲存輸入密碼的偏移地址
GETPW:
MOV AH,7 ;逐個字符輸入密碼,遇到回車結束輸入
INT 21H
CMP AL,0DH
JZ NEXT
CMP AL,08H
JE DELETE
MOV [SI],AL
MOV AH,2 ;在屏幕上顯示*
MOV DX,'*'
INT 21H
INC SI
INC BX ; 統計輸入密碼的長度
LOOP GETPW
DELETE:
CMP BX, 00H ; 如果刪除到第0個位置,再刪除就直接退出
JZ EXIT
DEC BX
CALL DELCODE
MOV AH,2 ;調用2號中斷,顯示空格,消除星號
MOV DL,' '
INT 21H
MOV BYTE PTR [SI],00H
DEC SI
CALL DELCODE
JMP GETPW
NEXT:
MOV CX,PWLEN
MOV BX,OFFSET BUF2
MOV SI,OFFSET BUF4
NEXT3:
MOV AL,[BX]
CMP [SI],AL
JNZ ERROR2
INC SI
INC BX
LOOP NEXT3 ;逐個字符比較BUF2和BUF4
MOV AH,9
MOV DX,OFFSET MESG3
INT 21H
JMP EXIT
DELCODE PROC
; 刪除一個字符,即把光標向左移動一格
MOV AH,3 ; 獲取光標位置
INT 10H
MOV AH,2 ;2號中斷:置光標位置
SUB DL,1 ;列數減1,實現光標左移
INT 10H
RET
DELCODE ENDP
ERROR1:
; 用戶名錯誤時報錯
MOV DX,OFFSET MESG4
CALL DISPMESS
ERROR2:
; 密碼錯誤時報錯
MOV DX,OFFSET MESG5
CALL DISPMESS
DISPMESS PROC
MOV AH,9
INT 21H
JMP EXIT
DISPMESS ENDP
EXIT:
MOV AH,4CH
INT 21H
CODE ENDS
END START