煎饼哥 發表於 2020-6-11 10:59:00

汇编语言的编写

<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]
查看完整版本: 汇编语言的编写