<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>汇编学习 on farmer3-c Blog</title><link>https://farmer3-c.github.io/tags/%E6%B1%87%E7%BC%96%E5%AD%A6%E4%B9%A0/</link><description>Recent content in 汇编学习 on farmer3-c Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 12 Jan 2026 17:54:28 +0800</lastBuildDate><atom:link href="https://farmer3-c.github.io/tags/%E6%B1%87%E7%BC%96%E5%AD%A6%E4%B9%A0/index.xml" rel="self" type="application/rss+xml"/><item><title>判断质数汇编程序编写</title><link>https://farmer3-c.github.io/posts/post-2026-01-12/</link><pubDate>Mon, 12 Jan 2026 17:54:28 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2026-01-12/</guid><description>&lt;p&gt;以下面的代码为例，说明如何用汇编语言判断一个数是否为素数，从而进行汇编语言的学习。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;pre&gt;&lt;code class="language-asm"&gt;
.MODEL SMALL
.STACK 100H
&lt;p&gt;.DATA
msg_input DB &amp;lsquo;Please input a number: $'
msg_prime DB 0DH, 0AH, 'It is a prime number.$&amp;rsquo;
msg_not DB 0DH, 0AH, &amp;lsquo;It is not a prime number.$&amp;rsquo;
num DW 0&lt;/p&gt;
&lt;p&gt;.CODE
START:
MOV AX, @DATA
MOV DS, AX&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;; 1. 显示输入提示
LEA DX, msg_input
MOV AH, 09H
INT 21H
; 2. 读取数字 (读取一个十进制数)
CALL READ_NUM
MOV num, AX
; 3. 判断素数逻辑
; 如果 n &amp;lt; 2，不是素数
CMP AX, 2
JL NOT_PRIME
JE IS_PRIME ; 2 是素数
; 循环判断: 从 2 到 n-1
MOV CX, 2 ; CX 是除数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CHECK_LOOP:
MOV AX, num
XOR DX, DX ; 清除高位
DIV CX ; AX / CX, 余数在 DX&lt;/p&gt;</description><content:encoded><![CDATA[<p>以下面的代码为例，说明如何用汇编语言判断一个数是否为素数，从而进行汇编语言的学习。</p>
<details>
<summary>点击展开/折叠代码</summary>
<pre><code class="language-asm">
.MODEL SMALL
.STACK 100H
<p>.DATA
msg_input  DB &lsquo;Please input a number: $'
    msg_prime  DB 0DH, 0AH, 'It is a prime number.$&rsquo;
msg_not    DB 0DH, 0AH, &lsquo;It is not a prime number.$&rsquo;
num        DW 0</p>
<p>.CODE
START:
MOV AX, @DATA
MOV DS, AX</p>
<pre><code>; 1. 显示输入提示  
LEA DX, msg_input
MOV AH, 09H
INT 21H

; 2. 读取数字 (读取一个十进制数)
CALL READ_NUM
MOV num, AX

; 3. 判断素数逻辑
; 如果 n &lt; 2，不是素数
CMP AX, 2
JL  NOT_PRIME
JE  IS_PRIME      ; 2 是素数

; 循环判断: 从 2 到 n-1
MOV CX, 2         ; CX 是除数
</code></pre>
<p>CHECK_LOOP:
MOV AX, num
XOR DX, DX        ; 清除高位
DIV CX            ; AX / CX, 余数在 DX</p>
<pre><code>CMP DX, 0         ; 如果余数为 0，说明被整除
JZ  NOT_PRIME

INC CX
MOV AX, CX
MUL AX            ; 计算 CX * CX
CMP AX, num       ; 只需检查到 根号 n 即可优化
JA  IS_PRIME      ; 如果 CX*CX &gt; num 还没除尽，就是素数

JMP CHECK_LOOP
</code></pre>
<p>IS_PRIME:
LEA DX, msg_prime
JMP DISPLAY</p>
<p>NOT_PRIME:
LEA DX, msg_not</p>
<p>DISPLAY:
MOV AH, 09H
INT 21H</p>
<pre><code>; 4. 退出程序
MOV AH, 4CH
INT 21H
</code></pre>
<p>; &mdash; 子程序：读取十进制数字 &mdash;
READ_NUM PROC
XOR BX, BX
READ_CHAR:
MOV AH, 01H       ; 读取字符到 AL
INT 21H
CMP AL, 0DH       ; 回车键退出
JZ  DONE_READ
SUB AL, &lsquo;0&rsquo;       ; 转换为数字
JL  DONE_READ
CMP AL, 9
JG  DONE_READ</p>
<pre><code>MOV AH, 0
PUSH AX
MOV AX, 10
MUL BX            ; BX = BX * 10
POP DX
ADD AX, DX
MOV BX, AX
JMP READ_CHAR
</code></pre>
<p>DONE_READ:
MOV AX, BX
RET
READ_NUM ENDP</p>
<p>END START
</code></pre></p>
</details>
<ul>
<li>
<p>首先是汇编程序的整体结构。</p>
<ul>
<li><code>.MODEL SMALL</code>：指定了程序的内存模型为 16 位。</li>
<li><code>.STACK 100H</code>：定义了堆栈段的大小为 100H。</li>
<li><code>.DATA</code>：定义了数据段，用于存储程序中的变量和常量。</li>
<li><code>.CODE</code>：定义了代码段，用于存储程序的指令。</li>
<li><code>START</code>：程序的入口点。</li>
<li><code>END START</code>：结束程序的定义。</li>
</ul>
</li>
<li>
<p>数据段：</p>
<ul>
<li><code>msg_input</code>：提示用户输入的字符串。</li>
<li><code>msg_prime</code>：输出素数的字符串。</li>
<li><code>msg_not</code>：输出非素数的字符串。</li>
<li><code>num</code>：用于存储用户输入的数字。</li>
</ul>
</li>
<li>
<p>代码段：</p>
<ul>
<li><code>START</code>：程序的入口点。</li>
<li><code>MOV AX, @DATA</code>：将数据段的地址加载到 AX 寄存器中。</li>
<li><code>MOV DS, AX</code>：将 AX 寄存器中的地址加载到 DS 寄存器中，设置数据段。</li>
<li>显示输入提示：
<ul>
<li><code>LEA DX, msg_input</code>：将 <code>msg_input</code> 的地址加载到 DX 寄存器中。</li>
<li><code>MOV AH, 09H</code>：设置 AH 寄存器为 09H，用于显示字符串。</li>
<li><code>INT 21H</code>：调用中断 21H，执行显示字符串的操作。</li>
</ul>
</li>
<li>读取数字：
<ul>
<li>调用 <code>READ_NUM</code> 子程序，将用户输入的数字存储在 <code>num</code> 中。</li>
</ul>
</li>
<li>判断素数逻辑：
<ul>
<li><code>CMP AX, 2</code>：比较 <code>AX</code> 寄存器中的值和 2。</li>
<li><code>JL NOT_PRIME</code>：如果 <code>AX</code> 小于 2，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li><code>JE IS_PRIME</code>：如果 <code>AX</code> 等于 2，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>循环判断：
<ul>
<li><code>MOV CX, 2</code>：将 2 加载到 CX 寄存器中，作为除数。</li>
<li><code>CHECK_LOOP</code>：循环标签。</li>
<li><code>MOV AX, num</code>：将 <code>num</code> 中的值加载到 AX 寄存器中。</li>
<li><code>XOR DX, DX</code>：将 DX 寄存器清零，用于存储余数。</li>
<li><code>DIV CX</code>：将 AX 寄存器中的值除以 CX 寄存器中的值，余数存储在 DX 寄存器中。</li>
<li><code>CMP DX, 0</code>：比较 DX 寄存器中的值和 0。</li>
<li><code>JZ NOT_PRIME</code>：如果 DX 等于 0，说明被整除，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li><code>INC CX</code>：将 CX 寄存器中的值加 1。</li>
<li><code>MOV AX, CX</code>：将 CX 寄存器中的值加载到 AX 寄存器中。</li>
<li><code>MUL AX</code>：将 AX 寄存器中的值乘以自身，结果存储在 AX 寄存器中。</li>
<li><code>CMP AX, num</code>：比较 AX 寄存器中的值和 <code>num</code> 中的值。</li>
<li><code>JA IS_PRIME</code>：如果 AX 大于 <code>num</code>，跳转到 <code>IS_PRIME</code> 标签。</li>
<li><code>JMP CHECK_LOOP</code>：跳转到 <code>CHECK_LOOP</code> 标签，继续循环。</li>
</ul>
</li>
<li><code>IS_PRIME</code>：如果是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li><code>NOT_PRIME</code>：如果不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
</ul>
</li>
<li>显示结果：
<ul>
<li>根据判断结果，加载相应的字符串到 DX 寄存器中。</li>
<li><code>MOV AH, 09H</code>：设置 AH 寄存器为 09H，用于显示字符串。</li>
<li><code>INT 21H</code>：调用中断 21H，执行显示字符串的操作。</li>
</ul>
</li>
<li>退出程序：
<ul>
<li><code>MOV AH, 4CH</code>：设置 AH 寄存器为 4CH，用于退出程序。</li>
<li><code>INT 21H</code>：调用中断 21H，执行退出程序的操作。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>子程序：</p>
<ul>
<li><code>READ_NUM</code>：用于读取用户输入的数字。
<ul>
<li><code>XOR BX, BX</code>：将 BX 寄存器清零，用于存储数字。</li>
<li><code>READ_CHAR</code>：循环标签。</li>
<li><code>MOV AH, 01H</code>：设置 AH 寄存器为 01H，用于读取字符。</li>
<li><code>INT 21H</code>：调用中断 21H，执行读取字符的操作。</li>
<li><code>CMP AL, 0DH</code>：比较 AL 寄存器中的值和回车键的 ASCII 码。</li>
<li><code>JZ DONE_READ</code>：如果 AL 等于回车键的 ASCII 码，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>SUB AL, '0'</code>：将 AL 寄存器中的值减去 &lsquo;0&rsquo; 的 ASCII 码，转换为数字。</li>
<li><code>CMP AL, 9</code>：比较 AL 寄存器中的值和 9。</li>
<li><code>JG DONE_READ</code>：如果 AL 大于 9，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>MOV AH, 0</code>：将 AH 寄存器清零。</li>
<li><code>PUSH AX</code>：将 AX 寄存器中的值压入堆栈。</li>
<li><code>MOV AX, 10</code>：将 10 加载到 AX 寄存器中。</li>
<li><code>MUL BX</code>：将 BX 寄存器中的值乘以 AX 寄存器中的值，结果存储在 AX 寄存器中。</li>
<li><code>POP DX</code>：将堆栈中的值弹出到 DX 寄存器中。</li>
<li><code>ADD AX, DX</code>：将 AX 寄存器中的值加上 DX 寄存器中的值，结果存储在 AX 寄存器中。</li>
<li><code>MOV BX, AX</code>：将 AX 寄存器中的值加载到 BX 寄存器中。</li>
<li><code>JMP READ_CHAR</code>：跳转到 <code>READ_CHAR</code> 标签，继续循环。</li>
<li><code>DONE_READ</code>：读取数字完成，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>MOV AX, BX</code>：将 BX 寄存器中的值加载到 AX 寄存器中。</li>
<li><code>RET</code>：返回。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>总结：</p>
<ul>
<li>该程序实现了判断一个数是否为素数的功能。</li>
<li>首先，程序显示输入提示，然后调用 <code>READ_NUM</code> 子程序读取用户输入的数字。</li>
<li>接下来，程序判断输入的数字是否小于 2，如果是，则不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li>如果输入的数字等于 2，则是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>如果输入的数字大于 2，则进入循环判断。</li>
<li>在循环中，程序将输入的数字除以从 2 到 <code>num-1</code> 的每个数，如果存在能整除的数，则不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li>如果循环结束后没有找到能整除的数，则是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>在 <code>IS_PRIME</code> 标签中，程序显示素数的字符串，并跳转到 <code>DISPLAY</code> 标签。</li>
<li>在 <code>NOT_PRIME</code> 标签中，程序显示非素数的字符串，并跳转到 <code>DISPLAY</code> 标签。</li>
<li>在 <code>DISPLAY</code> 标签中，程序调用中断 21H，执行显示字符串的操作。</li>
<li>最后，程序调用中断 21H，执行退出程序的操作。</li>
<li>该程序使用了堆栈来存储临时变量，以及一些寄存器来保存中间结果。</li>
<li>该程序的时间复杂度为 O(sqrt(n))，其中 n 为输入的数字。</li>
<li>该程序的空间复杂度为 O(1)，因为只使用了常数个变量。</li>
</ul>
</li>
</ul>
<p>设计编写汇编程序要注意的是合理分配堆栈空间，避免栈溢出。同时，要注意寄存器的使用，避免寄存器冲突。另外，要注意程序的可读性和可维护性，避免出现冗余代码。</p>
<hr>
<h2 id="参考">参考</h2>
<p><a href="/pdf/%E7%8E%8B%E7%88%BD%E7%BD%91%E8%AF%BEPPT.pdf">王爽网课</a></p>
]]></content:encoded></item></channel></rss>