汇编语言的编写
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>汇编运行过程<ul><li>准备</li><li>DOSBox,Link,Masm介绍<ul><li>Link和masm</li><li>DOSBox</li></ul></li><li>开始写程序<ul><li>此次用到的文件</li><li>利用masm.exe生成.OBJ文件</li><li>利用link.exe运行.OBJ文件,生成.exe文件</li><li>运行.exe文件</li><li>本次的代码</li></ul></li><li>大作业<ul><li>USE16的作用</li></ul></li></ul></li></ul></div><p></p><h1 id="汇编运行过程">汇编运行过程</h1>
<h2 id="准备">准备</h2>
<p>由于大多数<code>win10</code>系统都是<code>64</code>位系统,所以如果直接用<code>link.exe</code>和<code>masm.exe</code>来运行<code>asm</code>文件是不可以的。</p>
<p>所以需要安装<code>DOSBox</code></p>
<p><img src="https://i.loli.net/2020/06/11/QFidfDVHNb651Mq.png" alt="dosbox.PNG" loading="lazy"></p>
<h2 id="dosboxlinkmasm介绍">DOSBox,Link,Masm介绍</h2>
<h3 id="link和masm">Link和masm</h3>
<p> masm32包即可以支持开发在DOS操作系统下运行的16位应用程序,也可以开发在Windows操作系统下运行的32位应用程序。</p>
<p> <code>masm.exe</code>——汇编器。我们编写的源代码文件就是通过它来汇编生成中间代码文件,即通常扩展名为.obj的文件。<br>
<code>link16.exe</code>——连接器。由<code>masm.exe</code>汇编生成的<code>.obj</code>文件还不能直接上机运行,必须通过连接器<code>link16.exe</code>将其连接制作成扩展名为<code>.exe</code>(或者<code>.com</code>)的可执行文件才能上机。</p>
<p>但是我们主流的系统基本都是64位了,所以需要用<code>DOSBox</code>来给我们提供一个16位的<code>DOS</code>系统环境</p>
<h3 id="dosbox">DOSBox</h3>
<p>在现在的系统下模拟DOS环境的一个工具!是为了运行以前纯DOS环境下的软件而开发的!当然主要用途是运行原来的那些只能在DOS下玩的老游戏!</p>
<blockquote>
<p>使用方法:</p>
<ol>
<li>将存放masm、link和源程序文件的文件夹拷贝到某一目录下,比如c:\examples</li>
<li>然后将这个目录挂为DOSBox的一个盘符下,挂载命令为<br>
<code>Mount c c:\examples</code>; 可以理解为把当前工作目录切换到<code>c:\examples</code>这里,即<code>c:\examples</code>就是你以后的<code>C:</code></li>
<li>再切换到挂载的c盘:<br>
<code>c:</code>; 切换到工作目录</li>
</ol>
</blockquote>
<p><img src="https://i.loli.net/2020/06/11/GSqPaOgF5xAoncr.png" alt="mount.PNG" loading="lazy"></p>
<h2 id="开始写程序">开始写程序</h2>
<h3 id="此次用到的文件">此次用到的文件</h3>
<p>仔细对应DOSBox图片里面的代码和这个图片里面的文件</p>
<p><img src="https://i.loli.net/2020/06/11/16hUDtJbpznaYF2.png" alt="produce.PNG" loading="lazy"></p>
<h3 id="利用masmexe生成obj文件">利用masm.exe生成.OBJ文件</h3>
<p>在后缀名为<code>.asm</code>的文件中,编写完代码之后</p>
<p>在<code>DOSBox</code>中利用<code>masm.exe</code>运行<code>.asm</code>文件</p>
<pre><code class="language-assembly">masm yourfile.asm ; 注意,可以不加.asm后缀.不加的时候要保持名字不重复
</code></pre>
<p><img src="https://i.loli.net/2020/06/11/ghIX7lHBaAyb1Fj.png" alt="masm.PNG" loading="lazy"></p>
<h3 id="利用linkexe运行obj文件生成exe文件">利用link.exe运行.OBJ文件,生成.exe文件</h3>
<p>在<code>DOSBox</code>中利用<code>link.exe</code>运行<code>.OBJ</code>文件,然后生成<code>.exe</code>文件</p>
<pre><code class="language-assembly">link yourfile.OBJ; 注意,可以不加.OBJ后缀.不加的时候要保持名字不重复
</code></pre>
<p><img src="https://i.loli.net/2020/06/11/j8CkgKQqM3lipus.png" alt="link.PNG" loading="lazy"></p>
<blockquote>
<p>这里有warning L4021是因为我在写代码的时候没有定义堆栈区,但是没有关系</p>
<p>系统自动会帮我们建立堆栈区</p>
</blockquote>
<h3 id="运行exe文件">运行.exe文件</h3>
<p>在<code>DOSBox</code>中直接运行<code>.exe</code>文件<code>.OBJ</code>文件,然后生成<code>.exe</code>文件</p>
<p><img src="https://i.loli.net/2020/06/11/zy4uD9qJGPdCUj3.png" alt="exe.PNG" loading="lazy"></p>
<h3 id="本次的代码">本次的代码</h3>
<pre><code class="language-assembly">
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
</code></pre>
<h2 id="大作业">大作业</h2>
<h3 id="use16的作用">USE16的作用</h3>
<p>这句指的是,数据段采取16位来存取数据段中的数据。如果use32则是指用32位来存取数据段中的数据。具体的16还是32,根据你编程面向的cpu类型是16位的还是32位的。<br>
另外再补充一点点吧。<br>
cpu将内部存储单元分成许多逻辑段(Segment),这样,一个存储单元除具有一个唯一的物理地址外,还具有多个逻辑地址。<br>
data segment 指的就是数据段。<br>
数据段存放运行程序所用的数据。数据段寄存器DS存放数据段的段地址。各种主存寻址方式(有效地址EA)得到存储器中操作数的偏移地址。处理器利用DS:EA存取数据段中的数据。</p>
<pre><code class="language-assembly">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,
CMP ,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 ,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 ,00H
DEC SI
CALL DELCODE
JMP GETPW
NEXT:
MOV CX,PWLEN
MOV BX,OFFSET BUF2
MOV SI,OFFSET BUF4
NEXT3:
MOV AL,
CMP ,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
</code></pre>
</div>
<div id="MySignature" role="contentinfo">
有什么问题可以加qq:1281372141进行交流<br><br>
来源:https://www.cnblogs.com/WalterJ726/p/13091948.html
頁:
[1]