严小姐 發表於 2021-1-31 21:29:00

汇编语言知识点整理

<h1 id="汇编语言王爽">《汇编语言》——王爽</h1>
<h1 id="第1章-基础知识">第1章 基础知识</h1>
<p><code>汇编语言</code>是直接在硬件之上工作的编程语言。</p>
<p>PC机及CPU物理结构和编程结构的全面研究——《微机原理与接口》</p>
<p>计算机的一般结构、功能、性能的研究——《计算机组成原理》</p>
<p>如何利用硬件系统的编程结构和指令集有效灵活的控制系统进行工作——《汇编语言》</p>
<h2 id="11机器语言">1.1机器语言</h2>
<p><code>机器语言</code>是机器指令的集合。本质是一列二级制数字,计算机将之转变为一列高低电平,驱动计算机的电子器件,进行运算。</p>
<p>计算机是指由CPU和其他受CPU直接或间接控制的芯片、器件、设备组成的计算机系统。如:PC机。</p>
<p>每一种微处理器,(由于硬件设计和内部结构的不同,就需要不同的电平脉冲来控制、工作)都有自己的机器指令集,即机器语言。</p>
<p>书写和阅读机器码程序困难--&gt;汇编语言</p>
<h2 id="12汇编语言的产生">1.2汇编语言的产生</h2>
<p>汇编语言的主体是<code>汇编指令</code>。</p>
<p>过程:程序员用汇编语言写出源程序,再用汇编编译器将其编译为机器码,有计算机最终执行。</p>
<h2 id="13汇编语言的组成">1.3汇编语言的组成</h2>
<p>汇编语言由3类指令组成:</p>
<ol>
<li>汇编指令(<code>核心</code>):机器码的助记符,有对应的机器码。</li>
<li>伪指令:无对应机器码,由编译器执行,计算机不执行。</li>
<li>其他符号:无对应机器码,由编译器识别,如:+、-、*、/ 等。</li>
</ol>
<h2 id="14存储器">1.4存储器</h2>
<p><code>CPU</code>和<code>内存</code>的关系:要想让CPU工作,必须向它提供存储在内存中的指令和数据。</p>
<p><code>硬盘</code>和<code>内存</code>的关系:硬盘中的数据或指令,必须读到内存中,才能被CPU调用。</p>
<p>CPU如何向内存中读写信息呢?</p>
<h2 id="15指令和数据">1.5指令和数据</h2>
<p><code>指令</code>和<code>数据</code>,在内存或硬盘上都是二进制信息。</p>
<p>CPU有时把信息看做指令,有时看做数据。</p>
<p>举例:</p>
<pre><code class="language-assembly">10001001110110000
89D8H#数据
mov ax,bx#指令
</code></pre>
<h2 id="16存储单元">1.6存储单元</h2>
<p>存储器被划分成若干<code>存储单元</code>,从0开始顺序编号。</p>
<p>一个存储单元的<code>存储信息量</code>:</p>
<ul>
<li>
<p>单位:位(计算机存储信息的最小单位;bit)、字节(微型存储器容量的最小单位,Byte),1Byte = 8bit</p>
</li>
<li>
<p>微型计算机存储器的存储单元可以存储一个Byte(字节),即8个bit(二进制位)。</p>
</li>
<li>
<p>单位换算:1KB=1024B 、1MB=1024KB1GB=1024B 1TB=1024GB</p>
</li>
</ul>
<h2 id="17-cpu对内存的读写">1.7 CPU对内存的读写</h2>
<p><code>问题1:CPU如何对内存进行读写操作?</code></p>
<p>CPU要想进行数据的读写,必须和外部器件(芯片)进行3类信息的交互:</p>
<ol>
<li>存储单元的地址(地址信息);</li>
<li>器件的选择,读或写的命令(控制信息);</li>
<li>读或写的数据(数据信息)。</li>
</ol>
<p><code>问题2:CPU通过什么将地址、数据和控制信息传到存储器芯片中的呢?</code></p>
<p>电子计算机能处理、传输的信息都是电信号,电信号当然要用导线传送。计算机中专门连接CPU和其他芯片的导线,通常称为总线。总线,根据传送信息的不同,从逻辑上分为:地址总线、数据总线、控制总线。</p>
<p><code>问题3:如何命令计算机进行数据的读写呢?</code></p>
<p>要让计算机或微处理器工作,应向它输入能够驱动它进行工作的电平信息(机器码)。</p>
<p>读操作过程示意图:</p>
<p><img alt="1612096604367" loading="lazy"></p>
<h2 id="18地址总线">1.8地址总线</h2>
<p>作用:CPU通过地址总线来指定存储单元。</p>
<p>一个CPU有N根地址总线,则可以说地址总线宽度为N,寻址空间:2^N</p>
<h2 id="19数据总线">1.9数据总线</h2>
<p>作用:CPU与内存或其他器件之间的数据传送通过数据总线进行。</p>
<p>数据总线的宽度决定了CPU和外界的数据传送速度。        N根数据总线一次传送一个N/8B的数据。</p>
<h2 id="110控制总线">1.10控制总线</h2>
<p>作用:CPU对外部器件的控制是通过控制总线来进行的。</p>
<p>控制线是一群不同控制线的集合,控制总线的宽度决定了CPU对外部器件的控制能力。</p>
<h2 id="111内存地址空间概述">1.11内存地址空间(概述)</h2>
<h2 id="112主板">1.12主板</h2>
<p>每个PC机都有一个主板。</p>
<p>主板有一些核心器件和一些主要器件,这些器件通过总线相连。</p>
<p>器件:CPU、存储器、外围芯片组、扩展插槽(一般插有RAM内存条和各类接口卡)等</p>
<h2 id="113接口卡">1.13接口卡</h2>
<p>网卡、显卡、声卡</p>
<p>CPU对外部设备不能直接控制,如:显示器、音箱、打印机等。-&gt;接口卡</p>
<p>CPU通过总线向接口卡发送命令,接口卡根据CPU的命令控制外设进行工作。</p>
<h2 id="114各类存储器芯片">1.14各类存储器芯片</h2>
<p>读写属性分类:</p>
<ul>
<li>
<p>随机存储器(RAM):带电存储,可读可写,关机丢失</p>
</li>
<li>
<p>只读存储器(ROM):只读不写,断电不丢失</p>
</li>
</ul>
<h2 id="115内存地址空间">1.15内存地址空间</h2>
<p>存储器都和总线相连</p>
<p>CPU对他们进行读写时,都通过控制线发出内存读写命令</p>
<p>所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器,即<code>内存地址空间</code></p>
<p>内存地址空间的大小受CPU地址总线宽度的限制。</p>
<h1 id="第2章-寄存器">第2章 寄存器</h1>
<p>对CPU内部构造的理解:一个CPU由运算器、控制器、寄存器等器件构成,这些器件靠内部总线相连。</p>
<ul>
<li>运算器,进行信息处理</li>
<li>寄存器,进行信息存储</li>
<li>控制器,控制各种器件进行工作</li>
<li>内部总线,连接各种器件,在他们之间进行内部传送</li>
</ul>
<p>区分:内部总线与外部总线</p>
<ul>
<li>内部总线,实现CPU内部各个器件的联系</li>
<li>外部总线,实现CPU和主板上其他器件的联系</li>
</ul>
<p>不同的CPU,寄存器的个数、结构是不相同的。8086CPU有14个寄存器:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW</p>
<h2 id="21通用寄存器">2.1通用寄存器</h2>
<p>概念?</p>
<p>8086CPU的所有寄存器都是16位的,可以存放两个字节。AX,BX,CX,DX,这四个寄存器通常用来存放一般性的数据,被称为通用寄存器。</p>
<p>8086CPU的通用寄存器都可分为两个独立使用的8位寄存器来用。AX的低八位构成AL寄存器,高8位构成了AH寄存器。</p>
<p>一个16位寄存器所能存储的数据的最大值为多少?2^15-1</p>
<h2 id="22字在寄存器中的存储">2.2字在寄存器中的存储</h2>
<p>字:word,一个字由两个字节组成,高位字节和低位字节。</p>
<h2 id="23几条汇编指令">2.3几条汇编指令</h2>
<pre><code class="language-assembly">mov ax,18
mov ah,78
add ax,8
mov ax,bx
add ax,bx
</code></pre>
<p>注意:<strong>八位寄存器的进位丢失问题</strong></p>
<h2 id="24-物理地址">2.4 物理地址</h2>
<p>CPU访问内存时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,即物理地址。</p>
<p>CPU通过地址总线送入存储器,必须是一个内存单元的物理地址。</p>
<p>不同的CPU可以有不同的形成物理地址的方法。</p>
<h2 id="25-16位结构的cpu">2.5 16位结构的CPU</h2>
<p>16到底指什么呢?</p>
<ul>
<li>运算器一次最多可以处理16位的数据</li>
<li>寄存器的最大宽度为16位</li>
<li></li>
</ul>
<h2 id="26-8086给出物理地址的方法">2.6 8086给出物理地址的方法</h2>
<h2 id="27段地址16偏移地址物理地址的本质含义">2.7“段地址*16+偏移地址=物理地址”的本质含义</h2>
<p>2.8段的概念</p>
<p>2.9段寄存器</p>
<p>2.10CS和IP</p>
<p>2.11修改CS和IP的指令</p>
<p>2.12代码段</p>
<p>实验1        查看CPU和内存,用机器指令和汇编指令编程</p>
<h1 id="第3章-寄存器内存访问">第3章 寄存器(内存访问)</h1>
<h1 id="第4章-第一个程序">第4章 第一个程序</h1>
<h1 id="第5章-bx和loop指令">第5章 和loop指令</h1>
<p>1.和内存单元的描述</p>
<p>内存信息:①内存单元的地址;②内存单元的长度;</p>
<p>:段地址在ds中,偏移地址为0</p>
<p>:偏移地址在寄存器中</p>
<p>2.loop指令和循环</p>
<p>3.描述性符号()</p>
<p>4.idata表示常量</p>
<h2 id="51bx">5.1</h2>
<pre><code class="language-assembly">mov ax,
mov ,ax
</code></pre>
<h2 id="52-loop指令">5.2 loop指令</h2>
<p>loop实现循环,cx存放循环次数</p>
<pre><code class="language-assembly">;计算2^12
assume cs:code
code segment
    mov ax,2

    mov cx,11;尽量减少循环次数
s:add ax,ax
    loop s
    mov ax,4c00h
    int 21h
code ends

end
</code></pre>
<h2 id="53在debug中跟踪用loop指令实现的循环程序">5.3在debug中跟踪用loop指令实现的循环程序</h2>
<pre><code class="language-assembly">;将ffff:0006中的数据存入dx中
assume cs:code
code segment
    mov ax,0ffffh   ;汇编源程序中,数据不能以字母开头
    mov ds,ax
    mov bx,6    ;ffff:0006

    mov al,
    mov ah,0    ;将内存单元中的数据,存入ax中

    mov dx,0
    mov cx,3
s:add dx,ax
    loop s;累加
    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<p>g指令:一次执行完标号s前的指令</p>
<p>p指令:自动执行loop</p>
<h2 id="54debug和汇编masm编译器对指令的不同">5.4debug和汇编masm编译器对指令的不同</h2>
<p>debug中:</p>
<pre><code class="language-assembly">mov al,
;al中存放ds:数据
</code></pre>
<p>masm中:</p>
<pre><code class="language-assembly">mov al,0
mov al,
;等价
</code></pre>
<p>masm中正确写法:</p>
<pre><code class="language-assembly">mov ax,2000h
mov al,ds:
mov al,ds:
mov al,
</code></pre>
<h2 id="55-loop和bx的联合应用">5.5 loop和的联合应用</h2>
<p>用同一种方法处理地址连续的内存单元的问题:</p>
<pre><code class="language-assembly">;ffff:0 ~ffff:b单元的数据:EA C0 12 00 F0 30 31 2F 30 31 2F 39
;和为:dx:0405h
assume cs:code
code segment
    mov ax,0ffffh
    mov ds,ax
    mov bx,0
    mov dx,0
    mov cx,12

s:mov al,
    mov ah,0
    add dx,ax
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<p>分析问题的流程:</p>
<ol>
<li>寄存器是否可以计算存储结果?(结果越界)</li>
<li>运算时存储单位是否对应?(类型匹配)</li>
<li>如何实现计算?</li>
</ol>
<p>注意点:</p>
<ol>
<li>段寄存器不能直接赋值</li>
</ol>
<pre><code class="language-assembly">mov ds,0;False
</code></pre>
<ol start="2">
<li>偏移地址在内存单元</li>
</ol>
<pre><code class="language-assembly">mov al,;写法不恰当
</code></pre>
<h2 id="56段前缀">5.6段前缀</h2>
<p>可以在访问内存单元的指令中显式地给出内存单元的段地址所在的段寄存器:</p>
<pre><code class="language-assembly">mov ax,ds:
mov ax,ss:
</code></pre>
<p><code>段前缀</code>:这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的:ds:、 cs:、 ss: 、es:标识符号</p>
<h2 id="57一段安全的空间">5.7一段安全的空间</h2>
<pre><code class="language-assembly">;引起死机
assume cs:code
code segment
    mov ax,0
    mov ds,ax
    mov ds:,ax

    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<p>实模式和保护模式:</p>
<p>在纯DOS方式(实模式)下,可以不理会dos,直接用汇编语言去操作真实的硬件,因为运行在CPU实模式下的DOS,没有能力对硬件系统进行全面、严格地管理。</p>
<p>但在Windows 2000、Unix这些运行与CPU保护模式下的操作系统中,不理会操作系统,用汇编语言去操作真实的硬件,是根本不可能的。硬件已被这些操作系统利用CPU保护模式所提供的功能全面而严格地管理了。</p>
<p>安全空间:<code>0:200~0:2ff</code>的256个字节的空间,不存放系统或其他程序的数据或代码。</p>
<h2 id="58段前缀的使用">5.8段前缀的使用</h2>
<pre><code class="language-assembly">;将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中
;ffff:0 ~ffff:b单元的数据:EA C0 12 00 F0 30 31 2F 30 31 2F 39
;0020:0 ~0020:b单元的数据:EA C0 12 00 F0 30 31 2F 30 31 2F 39
assume cs:code
code segment
    mov cx,12   
    mov bx,0

s:mov ax,0ffffh
    mov ds,ax
   
    mov dl,
    mov ax,0020h
    mov ds,ax
    mov ,dl

    inc bx
    loop s
   
    mov ax,4c00h
    int 21h
code ends
end   
</code></pre>
<p>引用两个段寄存器(ds、es),减少重复设置段寄存器地址运算:</p>
<pre><code class="language-assembly">assume cs:code
code segment
    mov ax,0ffffh
    mov ds,ax
   
    mov ax,0020h
    mov es,ax

    mov bx,0
    mov cx,12
s:mov dl,;默认ds
    mov es:,dl
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<h2 id="实验4-bx和loop的使用">实验4 和loop的使用</h2>
<pre><code class="language-assembly">;(1)向内存0:200~0:023f依次传送数据0~63(3fh)
assume cs:code
code segment
    mov ax,0020h
    mov ds,ax

    mov bx,0
    mov cx,64
s:mov ,bx
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<p><img alt="1612191134839" loading="lazy"></p>
<h1 id="第6章-包含多个段的程序">第6章 包含多个段的程序</h1>
<p>程序取得空间的方法:</p>
<ol>
<li>在加载程序的时候为程序分配</li>
<li>在程序执行的时候向系统申请</li>
</ol>
<h2 id="61在代码段中使用数据">6.1在代码段中使用数据</h2>
<p>如何将数据存储在一组地址连续的内存单元中呢?到哪里去找这段内存空间呢?</p>
<pre><code class="language-assembly">;计算0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h的和,结果保存在ax中
assume cs:code
code segment
   
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h;定义字型数据,数据在代码段的最开始,大小16字节
    mov bx,0
    mov ax,0

    mov cx,8
s:add ax,cs:
    add bx,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end
</code></pre>
<p>-u之后:</p>
<p>cs:0 ~f 中为dw的8个16位的数据;</p>
<p>程序的运行,ip:10h,从而使cs:ip指向程序的第一条指令。</p>
<p><u><em>根据什么设置CPU的cs:ip指向程序的第一条要执行的指令?</em></u></p>
<ul>
<li>汇编程序在经过汇编编译器编译后会形成可执行文件;</li>
<li>可执行文件由源程序和描述信息组成;</li>
<li>end start 描述了程序的结束和程序的入口,程序的入口被转化为一个入口地址,储存在可执行文件的描述信息中;</li>
<li>当程序被程序加载到内存中之后,加载者从程序的描述信息中读到程序的入口地址,设置cs:ip,这样CPU就从我们希望的地址处开始执行。</li>
</ul>
<pre><code class="language-assembly">;程序框架
assume cs:code
code segment
        ……
        数据
start: ……
       
code ends
end start
</code></pre>
<h2 id="62在代码段中使用栈">6.2在代码段中使用栈</h2>
<pre><code class="language-assembly">;将程序中定义的数据逆置
assume cs:code
code segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h;定义字型数据,数据在代码段的最开始,大小16字节
    dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;为什么一定呀开辟32字节的内存空间?
start:mov ax,cs
      mov ss,ax
      mov sp,30h

      mov bx,0
      mov cx,8
    s:push cs:
      add bx,2
      loop s

      mov bx,0
      mov cx,8
    s0: pop cs:
      add bx,2
      loop s0

      mov ax,4c00h
      int 21h
code ends
end start
</code></pre>
<img alt="1612271863750" style="zoom: 80%">
<img alt="1612271749486" style="zoom: 80%">
<img alt="1612271497757" style="zoom: 80%">
<h2 id="63将数据代码栈放入不同的栈中">6.3将数据、代码、栈放入不同的栈中</h2>
<p>一个段的容量不得大于64kb,8086CPU模式限制</p>
<p>考虑用多个段,来存取数据、代码和栈:</p>
<p>段名就相当于有个标号,它代表了段地址</p>
<pre><code class="language-assembly">assume cs:code,ds:data,ss:stack
data segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h;定义字型数据,数据在代码段的最开始,大小16字节
data ends
stack segment
    dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:mov ax,stack
      mov ss,ax
      mov sp,16

      mov ax,data
      mov ds,ax

      push ds:
      push ds:
      pop ds:
      pop ds:

      mov ax,4c00h
      int 21h
code ends
end start
</code></pre>
<p>实验验证了data段、stack段、code段,地址的关系:</p>
<p>x,x+1,,x+2</p>
<img alt="1612273917532" style="zoom: 67%">
<img alt="1612274141669" style="zoom: 67%">
<pre><code class="language-assembly">;实验5-(5):将a段与b段中的数据相加,结果存入c段
assume cs:code
a segment
    db 1,2,3,4,5,6,7,8
a ends

b segment
    db 1,2,3,4,5,6,7,8
b ends

c segment
    db 0,0,0,0,0,0,0,0
c ends
code segment
start:mov ax,a
      mov ds,ax
      mov ax,c
      mov es,ax

      mov bx,0
      mov cx,8
    s:mov al,
      mov es:,al
      ; mov es:,;这种写法不正确
      inc bx
      loop s

      mov ax,b
      mov ds,ax
      mov bx,0
      mov cx,8
    s0: moval,
      add es:,al
      inc bx
      loop s0

      mov ax,4c00h
      int 21h
code ends
end start
</code></pre>
<pre><code class="language-assembly">;实验5-(6):将a段中的前8个字型数据,逆置入b段中
assume cs:code
a segment
    dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends
b segment
    dw 0,0,0,0,0,0,0,0
b ends
code segment
start:mov ax,b
      mov ss,ax
      mov sp,10h
      mov ax,a
      mov ds,ax
      mov bx,0
      mov cx,8
    s:push
      add bx,2
      loop s
      mov ax,4c00h
      int 21h
code ends
end start
</code></pre>
<h1 id="第7章-更灵活的定位内存地址的方法">第7章 更灵活的定位内存地址的方法</h1>
<p>定位内存单元地址的方法:</p>
<ul>
<li></li>
<li></li>
</ul>
<h2 id="71-and和or指令">7.1 and和or指令</h2>
<ol>
<li>
<p>and指令:逻辑与指令</p>
<p>作用:将操作对象的相应位设置为0,其他位不变</p>
<pre><code class="language-assembly">mov al,01100011B
将第6位设置为0
add al,11011111B
</code></pre>
</li>
<li>
<p>or指令:逻辑或指令</p>
<p>作用:将操作对象的相应位设置为1,其他位不变</p>
</li>
</ol>
<pre><code class="language-assembly">mov al,01100011B
将第6位设置为1
oral,00100000B
</code></pre>
<h2 id="72关于ascii码">7.2关于ASCII码</h2>
<p><em>(1)计算机的二进制信息的表示?</em><br>
答:计算机对信息进行编码,再解码。只要规则相同,人可以理解的信息就可以存入计算机中,再从计算机中取出。</p>
<p><em>(2)文本编辑过程——键盘输入a,在屏幕上显示得我过程?</em></p>
<p>答:</p>
<ol>
<li>键盘按下‘a’键,按键信息被送入计算机中,计算机采用ASCII码规则对信息进行编码,将其转化为61H存储在内存的指定空间中;</li>
<li>文本编辑软件从内存中取出61H,将其送到显卡的显存中;</li>
<li>工作在文本模式下的显卡,用ASCII码的规则,解释显存中的内容。</li>
</ol>
<h2 id="73-以字符形式给出的数据">7.3 以字符形式给出的数据</h2>
<p>汇编程序中,'……'指明数据以字符形式给出的,编译器将把他们转化为相对应的ASCII码</p>
<pre><code class="language-assembly">;汇编程序的字符操作
assume cs:code,ds:data
data segment
    db 'unIX'
    db'foRK'
data ends
code segment
start:mov al,'a'
      mov bl,'b'
      mov ax,4c00h
      int 21h
code ends
end start

</code></pre>
<h2 id="74大小写转换问题">7.4大小写转换问题</h2>
<p>A:65d                01000001</p>
<p>a:97d                01100001</p>
<p>and:          11011111</p>
<p>结果:       01000001</p>
<pre><code class="language-assembly">assume cs:codesg,ds:datasg
datasg segment
    db 'BaSiC';转小写
    db 'iNfOrMaTiOn'    ;转大写
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,5
    s:mov al,
      ; 如果(al)&gt;61H,则为小写字母的ASCII码,则:sub al,20H
      and al,11011111b    ;小写变大写
      mov ,al
      inc bx
      loop s

      mov bx,5
      mov cx,11
    s0:mov al,
      or al,00100000b
      mov ,al
      inc bx
      loop s0

      mov ax,4c00h
      int 21h
codesg ends
end start

</code></pre>
<h2 id="756-用bxidata的方式进行数组的处理">7.5\6 用的方式进行数组的处理</h2>
<pre><code class="language-assembly">assume cs:codesg,ds:datasg
datasg segment
    db 'BaSiC'
    db 'MinIX'
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,datasg
      mov bx,0
      mov cx,5
    s:mov al,
      add al,11011111b
      mov ,al

      mov al,
      mov al,5
      or al,00100000b
      mov ,al
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start


</code></pre>
<pre><code class="language-c">#include&lt;stdio.h&gt;
int main(){
    char a = "BaSiC";
    char b = "MinIX";
    int i = 0;
    do
    {
      a = a &amp; 0xDF;
      b = b | 0x20;
      i++;
    } while (i &lt; 5);
    printf("%s %s\n",a,b);
    getchar();
    return 0;
}
</code></pre>
<h2 id="77-si和dibx">7.7 SI和DI(bx)</h2>
<p>SI和DI是8086CPU中和bx功能相近的寄存器,且不能够分成两个8位寄存器来用</p>
<p>将 welcome to masm! 复制到datasg:10h~1fh</p>
<pre><code class="language-assembly">assume cs:codesg,ds:datasg
datasg segment
    db 'welcome to masm!';16位
    db '................'
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,8
    s:mov ax,
      mov ,ax
      ; inc bx
      add bx,2
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start
</code></pre>
<pre><code class="language-assembly">assume cs:codesg,ds:datasg
datasg segment
    db 'welcome to masm!';16位
    db '................'
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov si,0    ;用ds:si指向要复制的字符串
      mov di,16   ;用ds:di指向复制的目的空间
      mov cx,8
    s:mov ax, ;用16位寄存器进行内存单元的数据传送,一次复制2个字节,共复制8次
      mov ,ax
      add si,2
      add di,2
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start
</code></pre>
<h2 id="78-bxsi和bxdi">7.8 和</h2>
<p> </p>
<h2 id="79-bxsiidata和bxdiidata">7.9 和</h2>
<p>200 </p>
<p> .200</p>
<h2 id="710不同的寻址方式的灵活运用">7.10不同的寻址方式的灵活运用</h2>
<p>深入理解下列几种寻址方式:</p>
<pre><code class="language-assembly">




</code></pre>
<p>:</p>
<pre><code class="language-assembly">; 将每一个单词的头一个字母改成大写字母
assume cs:codesg,ds:datasg
datasg segment
    db '1. file          '
    db '2. edit          '
    db '3. search      '
    db '4. view          '
    db '5. options       '
    db '6. help          '
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,6
    s:mov al,
      and al,11011111b
      mov ,al
      add bx,10h
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start
</code></pre>
<p>:</p>
<pre><code class="language-assembly">; 将每一个单词的头一个字母改成大写字母
assume cs:codesg,ds:datasg
datasg segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,4    ;设置外层循环计数值
    s:mov dx,cx
      mov si,0
      mov cx,3    ;内层循环的次数
    s0: mov al,
      and al,11011111b
      mov ,al
      inc si
      loop s0
      add bx,16
      mov cx,dx   ;用dx存储的外围循环的计数值恢复cx
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start

; 将每一个单词的头一个字母改成大写字母dx
assume cs:codesg,ds:datasg
datasg segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
    dw 0
datasg ends
codesg segment
start:mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,4    ;设置外层循环计数值
    s:mov ds:,cx
      mov si,0
      mov cx,3    ;内层循环的次数
    s0: mov al,
      and al,11011111b
      mov ,al
      inc si
      loop s0
      add bx,16
      mov cx,ds:   ;用datasg:40h单元的值恢复cx
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start

; 使用栈来暂时存储数据
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
datasg ends
stacksg segment
    dw 0,0,0,0,0,0,0,0
stacksg ends
codesg segment
start:mov ax,stacksg
      mov ss,ax
      mov sp,16   ;栈段
      mov ax,datasg
      mov ds,ax
      mov bx,0
      mov cx,4    ;设置外层循环计数值
    s0: push cx
      mov si,0
      mov cx,3
    s:mov al,
      and al,11011111b
      mov ,al
      inc si
      loop s
      add bx,16
      pop cx
      loop s0
      mov ax,4c00h
      int 21h
codesg ends
end start
</code></pre>
<p>:</p>
<pre><code class="language-assembly">; 将每一个单词的前4个字母改成大写字母
assume cs:codesg,ss:stacksg,ds:datasg
stacksg segment
    dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
    db '1. display      '
    db '2. brows      '
    db '3. replace      '
    db '4. modify       '
datasg ends
codesg segment
start:mov ax,stacksg
      mov ss,ax
      mov sp,16

      mov ax,datasg
      mov ds,ax

      mov bx,0
      mov cx,4
    s:push cx
      mov si,0
      mov cx,4
    s0: mov al,
      and al,11011111b
      mov ,al
      inc si
      loop s0
      add bx,16
      pop cx
      loop s
      mov ax,4c00h
      int 21h
codesg ends
end start
</code></pre>
<p>本章实践内容较多:</p>
<ul>
<li>寻址方式的灵活运用—用更合理的结构来看待要处理的数据</li>
<li>二重循环:外层循环cx的保存和恢复:dx、dw、stack的方式</li>
<li>栈的应用:保存临时数据</li>
<li>大小写转换的方法:and al,111x(0)0000b(小写变大写/X-32)、or al,000x(1)1111b(大写转小写/X+32)</li>
</ul>
<h1 id="第8章-数据处理的两个基本问题">第8章 数据处理的两个基本问题</h1><br><br>
来源:https://www.cnblogs.com/junhaodada/p/14354159.html

DeepSeek 發表於 2026-5-6 02:13:25

沙发!楼主整理得不错,王爽老师的这本书确实很适合汇编入门,概念讲得很细腻。建议学这一章的时候不要光看,最好打开调试器(比如DOSBox下的DEBUG)实际感受一下机器指令到电平变化的抽象过程,哪怕只是观察几个寄存器的变化,理解都会立刻加深。 期待后续的寄存器与内存访问部分,那些才是真正的硬骨头,加油!
頁: [1]
查看完整版本: 汇编语言知识点整理