弘兴 發表於 2020-12-25 09:26:00

汇编语言实验总结

<h2>实验一</h2>
<h3>四、实验结论</h3>
<h4>1.&nbsp;教材实验1(P45)</h4>
<h5>(1)使用Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后CPU中相关寄存器的内容变化</h5>
<p>使用e命令修改内存:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010192728740-943911731.jpg"></p>
<p>使用a命令修改内存:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010192840088-222031490.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010192950193-463064603.jpg"></p>
<h5>(2)将下面3条指令写入从2000:0开始的内存单元中,利用这三条指令计算2的8次方</h5>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010193035806-602322201.jpg"></p>
<p>单步调试:</p>
<p>&nbsp;开始部分:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010193550877-1133009389.jpg"></p>
<p>结束部分:ax=0100H</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010193700092-310456346.jpg"></p>
<h5>(3)查看内存中的内容</h5>
<p>从FFF00开始查看</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010194433357-1248777099.jpg"></p>
<p>生产日期应为01/01/92。尝试修改生产日期:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010194548750-1838830150.jpg"></p>
<p>使用e命令修改内存后发现数据未被修改。由此可知生产日期在只读的地址空间,所以只能读取,不能写入。结合当前时间来看ROM的生产日期是虚拟的。</p>
<h5>(4)向内存从B8100H开始的单元填写数据</h5>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010200325946-644623379.jpg"></p>
<p>向B8100H地址写入数据后在窗口中出现了图像。翻阅教材1.15节得知A0000H~BFFFFH为显存地址空间。向这些内存单元写数据,就是向显存中写入数据,这些数据会被显示卡输出到显示器上。</p>
<h4>2.&nbsp; 教材实验2(P74)</h4>
<h5>(1)使用Debug,将下面的程序段写入内存,逐条执行,根据指令执行后的实际情况填空</h5>
<p>首先使用 e 命令修改 内存单元0022:0~0022:f 中的数据,及修改后使用d命令查看是否正确写入</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010200819842-521025097.jpg"></p>
<p>使用 a 命令输入汇编指令并填空</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203147249-1816439137.jpg"></p>
<p>单步调试</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203301448-1837156350.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203348607-760869810.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203425542-755583102.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203608248-1274846432.jpg"></p>
<p>push&nbsp;ax后2200:00FE中的内容</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010203943187-1092402885.jpg"></p>
<p>push&nbsp;bx后2200:00FC中的内容</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010204038738-1067391853.jpg"></p>
<p>push 后2200:00FE中的内容</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010204210893-1274429012.jpg"></p>
<p>push 后2200:00FC中的内容</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010204237617-1887768407.jpg"></p>
<p>与之前的理论填空结果相比较,可知结果正确</p>
<h5>(2)进行以下实验,并分析:为什么2000:0~2000:f中的内容会发生改变?</h5>
<p>图 3.19 中使用 a命令输入的 7 行指令,使用 e 命令修改 2000:0~2000:f 的值,及修改后查看的部分</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010204331259-1707885496.jpg"></p>
<p>单步调试每一行汇编指令的截图。每一条指令单步调试后,都使用d命令查看2000:0~2000:f 的值。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010204757218-1992257764.jpg"></p>
<p>观察上图,发现执行momv ss, ax与mov&nbsp;sp, 10后2000:0~2000:f中的内容发生改变,继续调试</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010205921668-1513415191.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201010210238816-1365270790.jpg"></p>
<p>观察上图可知,红框中内容没有发生改变,且其中073FH与CS寄存器的值相对应,①的值与AX寄存器的值相对应,②的值与IP寄存器的值相对应,③为栈中存储的数据。通过了解,知道DOS系统中只有一个栈,系统会用该栈暂存相关数据。</p>
<p>以文字方式陈述:</p>
<p>1)前三行汇编指令的功能是什么?特别是,mov sp, 10意味着什么?初始时栈顶和栈底分别是?</p>
<div class="cnblogs_code">
<pre>mov ax, 2000      ; 将2000H送至ax寄存器
mov ss, ax      ; 将ax寄存器的值送至ss栈顶段地址寄存器
mov sp, 10      ; 将0010H送至sp栈顶偏移地址寄存器</pre>
</div>
<p>初始时栈顶为2000:0010,栈底为2000:000e。</p>
<p>2)基于单步调试观察到的变化,给出你对此的思考及可能原因分析</p>
<p>通过单步调试以及查阅资料,知道DOS系统中只有一个栈,系统会用该栈暂存相关数据,因此内存单元中的值会被修改。</p>
<h2>实验二</h2>
<h3>四、实验结论</h3>
<h4>1. 实验任务1</h4>
<p>给出ex1.asm源代码</p>
<div class="cnblogs_code">
<pre>; ex1.asm
assume cs:<span>code
code segment
    mov<span> ax, 0b810h
    mov<span> ds, ax

    mov byte ptr ds:, 1
    mov byte ptr ds:, 1
    mov byte ptr ds:, 2
    mov byte ptr ds:, 2
    mov byte ptr ds:, 3
    mov byte ptr ds:, 3
    mov byte ptr ds:, 4
    mov byte ptr ds:, 4
    mov<span> ah, 4ch

    int<span> 21h
    code ends
end</span></span></span></span></span></pre>
</div>
<p>给出使用masm、link工具汇编、链接的命令行及运行结果截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031200612882-164965428.jpg"></p>
<p>给出使用debug调试的截图。结合可执行文件加载后寄存器CX的值,使用u命令精确反汇编截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031200701908-95003361.jpg"></p>
<p>查看PSP的命令及截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031200825343-75770435.jpg"></p>
<p>使用g命令执行到line16退出执行之前,操作截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031200927770-1840309703.jpg"></p>
<h4>2.&nbsp;实验任务2</h4>
<p>给出ex2.asm源代码</p>
<div class="cnblogs_code">
<pre>; ex2.asm
assume cs:<span>code
code segment
    mov<span> ax, 0b810h
    mov<span> ds, ax

    mov bx, 0
    mov<span> ax, 101H
    mov cx, 4
s:mov<span> , ax
    add bx, 2
    add<span> ax, 101H
    loop s

    mov<span> ah, 4ch
    int<span> 21h
code ends
end</span></span></span></span></span></span></span></span></pre>
</div>
<p>给出使用masm、link工具汇编、链接的命令行及运行结果截图</p>
<blockquote>
<p>图不放了</p>
</blockquote>
<p>给出使用debug调试的截图。结合可执行文件加载后寄存器CX的值,使用u命令精确反汇编截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031201359435-16923477.jpg"></p>
<p>灵活使用t命令/p命令、g命令,对ex2.exe进行调试的截图</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031201425421-854051436.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031201459135-319113043.jpg"></p>
<p>回答问题</p>
<blockquote>
<p>结合上述实验和观察,分析、对比ex2.asm和ex1.asm,它们实现的是否是相同的功能和效果?在具体实现上有什么不同?</p>
</blockquote>
<p>答:作用相同,都是向b810:0000开始的内存空间中写入0101 0202 0303 0404四个字。在具体实现上,ex1.asm使用8行(几乎)重复的代码完成写入操作,而ex2.asm使用了loop结构完成写入操作。</p>
<h4>3.&nbsp;实验任务3</h4>
<p>给出源代码</p>
<div class="cnblogs_code">
<pre>; ex3.asm
assume cs:<span>code
code segment
    mov<span> ax, 0b800h
    mov<span> ds, ax

    mov<span> bx, 07b8h
    mov cx, 16

s:mov<span> , 0237h
    inc<span> bx
    inc<span> bx
    loop s

    mov<span> ah, 4ch
    int<span> 21h
code ends
end</span></span></span></span></span></span></span></span></span></pre>
</div>
<p>给出运行结果截图</p>
<blockquote>
<p>屏幕中间绿色的7</p>
</blockquote>
<p>把填充的字数据,从0237H 改成0239H,再次保存后,汇编、链接、运行,观察结果。</p>
<blockquote>
<p>屏幕中间绿色的9</p>
</blockquote>
<p>把填充的字数据,从0237H 改成0437H,再次保存后,汇编、链接、运行,观察结果。</p>
<blockquote>
<p>屏幕中间红色的7</p>
</blockquote>
<p>&nbsp;</p>
<blockquote>
<p>猜测并分析,这个字数据中高位字节里存放的是什么信息,低位字节里存放的是什么信息。</p>
</blockquote>
<p>容易想到,37h为字符'7'对应的ASCII码,39h为字符'9'对应的ASCII码。在网络上检索到相关资料:</p>
<p>Reference:(Belal&nbsp;Hashmi,&nbsp;Assembly Language Programming Lecture Notes, Chap. 6)</p>
<blockquote>
<p>The video device is seen by the computer as a memory area containing the ASCII codes that are currently displayed on the screen ......&nbsp;Therefore if that appropriate block of the screen is cleared, the screen will be cleared. If the&nbsp;ASCII of ‘A’ is placed somewhere in that block, the shape of ‘A’ will appear on&nbsp;the screen at a corresponding place ......&nbsp;&nbsp;This correspondence must be defined as the memory is a single&nbsp;dimensional space while the screen is two dimensional having 25 rows and&nbsp;80 columns. The memory is linearly mapped on this two dimensional space,&nbsp;just like a two dimensional is mapped in linear memory.&nbsp;<strong>There is one word&nbsp;per character in which a byte is needed for the ASCII code and the other byte&nbsp;is used for the character’s attributes discussed later.</strong>&nbsp;Now the first 80 words&nbsp;will correspond to the first row of the screen and the next 80 words will&nbsp;correspond to the next row. By making the memory on the video controller&nbsp;accessible to the processor via the system bus, the processor is now in&nbsp;control of what is displayed on the screen ......&nbsp;&nbsp;It was fixed at the physical memory location of&nbsp;B8000.&nbsp;<strong>The first byte at this location contains the ASCII for the character&nbsp;displayed at the top left of the video screen</strong>&nbsp;......&nbsp;<strong>The second byte in the word designated for one screen location holds the&nbsp;foreground and background colors for the character. This is called its video&nbsp;attribute.</strong>&nbsp;So the pair of the ASCII code in one byte and the attribute in the&nbsp;second byte makes the word that corresponds to one location on the screen.&nbsp;<strong>The lower address contains the code while the higher one contains the&nbsp;attribute.</strong>&nbsp;The attribute byte as detailed below has the RGB for the foreground and the background.</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031204731198-1131594882.jpg"></p>
</blockquote>
<p>由于0x07b8 = 1976 = 988*2 = (12*80+28)*2,因此向b800:07b8写入数据就相当于向显示器第13行第29个字符位置写入数据。同时,0x0237就表示前景颜色为绿色的字符'7';0x0239就表示前景颜色为绿色的字符'9';0x0437就表示前景颜色为红色的字符'7'。从下图也可以看出第一个字符出现的位置正是显示器第13行第29个字符。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031211327337-644364478.jpg"></p>
<p>同理,0x1737就表示前景颜色为白色、背景颜色为蓝色的字符'7'。</p>
<blockquote>
<p>图片</p>
</blockquote>
<h4>4.&nbsp;实验任务4</h4>
<blockquote>
<p>编写完整汇编源程序,实现向内存0:200~0:23F依次传送数据0~63(3FH)。</p>
<p>Tips:<br>这道练习,本质上就是把一组连续的字节数据(常数),送到指定的连续的字节单元。<br>如果利用栈实现,借助push和loop实现连续入栈操作。需要注意:<br>① 初始时ss和sp的设置<br>② 8086的入栈操作,是从高地址单元→低地址单元方向的;<br>③ 8086的入栈操作,只能以字为单元。但这里是字节数据,如何灵活处理?</p>
</blockquote>
<p>程序源代码</p>
<div class="cnblogs_code">
<pre> 1 ; ex4.asm
2 assume cs:<span>code
3 <span>code segment
4   mov ax, 0
5   mov<span> ds, ax
6
7   mov<span> bx, 200h
8   mov al, 0
9   mov<span> cx, 40h
10
11 ; clear memory
12 t:mov byte ptr , 0
13   inc<span> bx
14 <span>    loop t
15   mov<span> bx, 200h
16   mov<span> cx, 40h
17
18 s:mov<span> byte ptr , al
19   inc<span> bx
20   inc<span> al
21 <span>    loop s
22
23   mov<span> ah, 4ch
24   int<span> 21h
25 <span>code ends
26 end</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>汇编、链接无误后,灵活使用debug的t命令、g命令、p命令调试,用d命令查看0:200~0:23F,确认是否将0~63传送至此段内存区域。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031211959948-1736583125.jpg"></p>
<p>首先执行至Line 17,确保0:200h附近的空间数据为0;然后执行至Line 23,查看内存。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031212302820-1819474741.jpg"></p>
<p>可见0~63被正确传送至此段内存区域。</p>
<h4>5.&nbsp;实验任务5</h4>
<blockquote>
<p>教材实验4(3)(P121)<br>Tips:<br>这道练习,本质仍然是复制,只不过复制的是自身代码。填空的关键是,如何确定复制多少字节。</p>
</blockquote>
<p>填空以后的源代码</p>
<div class="cnblogs_code">
<pre> 1 ; ex5.asm
2 assume cs:<span>code
3 <span>code segment
4   mov<span> ax, <span style="text-decoration: underline">cs </span>
5   mov<span> ds, ax
6
7   mov<span> ax, 20h
8   mov<span> es, ax
9
10   mov bx, 0
11   mov<span> cx, <span style="text-decoration: underline">0 </span>
12
13 s:mov<span> al,
14   mov es:<span>, al
15   inc<span> bx
16 <span>    loop s
17
18   mov<span> ah, 4ch
19   int<span> 21h
20 <span>code ends
21 end</span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>以文字方式说明空白处填写依据</p>
</blockquote>
<p>注意Line 11中cx首先被置为0。为了确定Line 1 - 16的指令长度,cx首先被置为0,接着通过对程序进行debug查看Line 1 - 16的指令长度,再将Line 11修改为该长度。将ax设为cs是因为确定代码段起始位置。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031213409789-438240631.jpg"></p>
<p>由上图看出,将cx修改为16h即可。修改之后再次编译、链接。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031213519619-1737611216.jpg"></p>
<p>首先查看20:0附近的内存,可以看出内存中的数据仍为实验4中移动的数据。程序执行至Line 17,再次查看内存。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031213556666-34820202.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031214031607-3592043.jpg"></p>
<p>可以看出程序被成功复制。</p>
<h4>6.&nbsp;实验任务6</h4>
<blockquote>
<p>在linux环境下,编写、汇编、运行、调试一个32位的Intel风格的x86汇编程序。</p>
</blockquote>
<p>源代码</p>
<div class="cnblogs_code">
<pre> 1 ; example.asm
2
3 <span>global _start
4
5 <span>section .data
6   msg db "a simple test"<span>, 0xa
7 <span>    len equ $ - msg
8
9 <span>section .text
10 _start:
11   mov eax, 4
12   mov ebx, 1
13   mov<span> ecx, msg
14   mov<span> edx, len
15   int<span> 0x80
16
17   mov eax, 1
18   mov ebx, 7
19   int 0x80</span></span></span></span></span></span></span></span></pre>
</div>
<p>对example.asm进行汇编、链接、运行。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031215325548-1969229160.jpg"></p>
<p>将example.asm中line18行中寄存器ebx的值改为7,重新汇编、链接、运行。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202010/2175620-20201031215448445-765301384.jpg"></p>
<h3>五、实验总结</h3>
<h4>关于DOS程序运行结束后的返回</h4>
<p>在以上ex1-ex5中,程序均包含以下两行代码</p>
<div class="cnblogs_code">
<pre>mov<span> ah, 4ch
int 21h</span></pre>
</div>
<p>翻阅书本,在P81有</p>
<blockquote>
<p>这两条指令所实现的功能就是程序返回。</p>
<p>在目前阶段,我们不必去理解int 21h指令的含义,和为什么要在这条指令的前面加上指令mov&nbsp;ax, 4c00h。我们只要知道,在程序的末尾使用这两条指令就可以实现程序返回。</p>
</blockquote>
<p>此两行代码涉及DOS中Interrupt(中断)的知识,详细内容可在书本Chap. 12-13被参照。此处仅做最基本的介绍。int为一条x86指令,其作用为产生软件中断,</p>
<blockquote>
<p>在计算机科学中,<strong>中断</strong>(<span lang="en">Interrupt)是指处理器接收到来自硬件或软件的信号,提示发生了某个事件,应该被注意,这种情况就称为中断。<em>软件中断</em>。是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态(Kernel Mode/Ring 0)的子例程,它常被用作实现系统调用。</span></p>
</blockquote>
<p>int指令的格式为</p>
<div class="cnblogs_code">
<pre>int X</pre>
</div>
<p>其中X用于指出具体的中断。int 21h表示调用系统服务。该指令根据ax寄存器的高字节(ah)中的数据,又可实现不同的功能。当ah为4ch时,表示终止程序。故程序均包含该两行代码以正常退出。对于其它的中断,读者可参照该网站以及该pdf获取更多信息。</p>
<h2>实验三</h2>
<h3>四、实验结论</h3>
<h4>1. 实验任务1</h4>
<blockquote>
<p>附上源代码文件task1.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:<span>data
2 <span>data segment
3         db 'Nuist'
4         db 5 dup(2)
5 <span>data ends
6
7 <span>code segment
8 start:
9         mov<span> ax, data
10         mov<span> ds, ax
11
12         mov<span> ax, 0b800H
13         mov<span> es, ax
14
15         mov cx, 5
16         mov si, 0
17         mov<span> di, 0f00h
18 s:      mov<span> al,
19         and<span> al, 0dfh
20         mov es:<span>, al
21         mov al,
22         mov es:, al
23         inc<span> si
24         add di, 2
25 <span>      loop s
26
27         mov<span> ah, 4ch
28         int<span> 21h
29 <span>code ends
30 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上运行结果截图</p>
</blockquote>
<p>不贴了</p>
<p>可以看到在窗口左下角出现了绿色的字符串“NUIST”。</p>
<blockquote>
<p>附上在debug里调试到程序返回前的截图</p>
</blockquote>
<p>首先反汇编,查看指令地址</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121170251591-1854100030.jpg"></p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121170632684-1601010088.jpg"></p>
<p>可以看出程序退出前的指令地址为27。使用g命令执行至程序退出前。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121170743872-1616844122.jpg"></p>
<blockquote>
<p>修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。</p>
</blockquote>
<div class="cnblogs_code">
<pre>db 5 dup(2<span>)
--&gt; 改成:<span>
db 2,3,4,5,6</span></span></pre>
</div>
<p>运行结果为</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121172001921-692153654.jpg"></p>
<p>可以看出字符颜色改变。</p>
<blockquote>
<p>分析源代码中data段line4的字节数据的用途</p>
</blockquote>
<p>在上一次实验的实验任务3中,我已经查阅了相关资料并得到了结论。这里再次对结论进行简要的陈述。</p>
<p>Line4中的5个字节数据为Line3中5个字符的显示属性(video&nbsp;attribute),用于控制对应的字符的显示效果。显示属性的8个比特位的含义如下图所示。</p>
<blockquote>
<p>图前面有。</p>
</blockquote>
<p>所以2(10B)代表前景颜色为绿色;3(11B)代表前景颜色为蓝绿色;4(100B)代表前景颜色为红色;5(101B)代表前景颜色为紫色;6(110B)代表前景颜色为黄色。与实际结果相符。</p>
<h4>2.&nbsp;实验任务2</h4>
<blockquote>
<p>编写程序,在屏幕上以十进制整数形式打印输出这5个两位数。</p>
</blockquote>
<p>1个两位数如何输出:</p>
<p>具体处理步骤如下:<br>第1步,利用除法指令div,计算出每个数位上的数值。<br>第2步,利用数值和数字字符之间ascⅡ码的关系,把数值→数字字符<br>第3步,利用系统功能调用int 21h中的2号子功能,输出单个字符。</p>
<p>int 21h中的2号子功能说明如下:<br>功能:输出单个字符<br>用法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">mov</span> ah, <span style="color: rgba(128, 0, 128, 1)">2</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> dl, ×× <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> ××是待输出的字符,或其ASCII码值</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> 21h</pre>
</div>
<blockquote>
<p>附上源代码文件task2.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 ; task2.asm
2 assume cs:code, ds:<span>data
3 <span>data segment
4   db 23, 50, 66, 71, 35
5 <span>data ends
6 <span>code segment
7 start:mov<span> ax, data
8   mov<span> ds, ax
9
10   mov bl, 10
11   mov cx, 5
12   mov si, 0
13 s:      mov ax, 0
14   mov<span> al,
15   div<span> bl
16   add<span> al, 30h
17   mov<span> dl, al
18   mov<span> bh, ah
19   mov ah, 2
20   int<span> 21h
21   mov<span> al, bh
22   add<span> al, 30h
23   mov<span> dl, al
24   int<span> 21h
25   inc<span> si
26 <span>    loop s
27
28   mov<span> ah, 4ch
29   int<span> 21h
30 <span>code ends
31 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上运行结果截图</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121190954971-228489001.jpg"></p>
<h4>3.&nbsp;实验任务3</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(1)</p>
<blockquote>
<p>附上源代码文件task3.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:data, ss:<span>stack
2 <span>data segment
3 <span>dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
4 <span>data ends
5
6 <span>stack segment
7   dw 0, 0, 0, 0, 0, 0, 0, 0
8 <span>stack ends
9
10 <span>code segment
11 start:mov<span> ax,stack
12         mov<span> ss, ax
13         mov sp,16
14         
15         mov<span> ax, data
16         mov<span> ds, ax
17         
18         push ds:
19         push ds:
20         pop ds:
21         pop ds:
22         
23         mov<span> ax,4c00h
24         int<span> 21h
25
26 <span>code ends
27 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>回答教材中①②③三个问题。</p>
</blockquote>
<p>①&nbsp;data段中的数据没有改变,为0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h。</p>
<p>②&nbsp;cs =&nbsp;076ch, ss =&nbsp;076bh, ds =&nbsp;076ah。</p>
<p>③&nbsp;data段的段地址为X-2,stack段的段地址为X-1。</p>
<blockquote>
<p>附上回答①时,反汇编查看data段中数据的截图。验证观察到的结果和理论分析是否一致。</p>
</blockquote>
<p>首先对程序反汇编,查看指令地址</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121191304667-771907569.jpg"></p>
<p>运行至程序退出前,查看data段中的数据。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121191336210-520551421.jpg"></p>
<p>可以看出与理论结果相符合。</p>
<blockquote>
<p>附上回答②时反汇编调试截图,即:在debug中,执行到程序返回前的调试截图。</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121191336210-520551421.jpg"></p>
<h4>4.&nbsp;实验任务4</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(2)</p>
<blockquote>
<p>附上源代码文件task4.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:data, ss:<span>stack
2 <span>data segment
3 <span>dw 0123h, 0456h
4 <span>data ends
5
6 <span>stack segment
7   dw 0, 0
8 <span>stack ends
9
10 <span>code segment
11 start:mov<span> ax,stack
12         mov<span> ss, ax
13         mov sp,16
14         
15         mov<span> ax, data
16         mov<span> ds, ax
17         
18         push ds:
19         push ds:
20         pop ds:
21         pop ds:
22         
23         mov<span> ax,4c00h
24         int<span> 21h
25
26 <span>code ends
27 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>回答教材中①②③④四个问题。</p>
</blockquote>
<p>①&nbsp;data段中数据不变,为0123h,0456h。</p>
<p>②&nbsp;cs =&nbsp;076ch, ss =&nbsp;076bh, ds =&nbsp;076ah。</p>
<p>③&nbsp;data段的段地址为X-2,stack段的段地址为X-1。</p>
<p>④&nbsp;该段实际占有的空间为(N/16+1)*16。</p>
<blockquote>
<p>附上回答②时反汇编调试截图,即:在debug中,执行到程序返回前的调试截图。</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121191737618-91005950.jpg"></p>
<h4>5.&nbsp;实验任务5</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(3)</p>
<blockquote>
<p>附上源代码文件task5.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:data, ss:<span>stack
2
3 <span>code segment
4 start:mov<span> ax,stack
5         mov<span> ss, ax
6         mov sp,16
7         
8         mov<span> ax, data
9         mov<span> ds, ax
10         
11         push ds:
12         push ds:
13         pop ds:
14         pop ds:
15         
16         mov<span> ax,4c00h
17         int<span> 21h
18
19 <span>code ends
20 <span>data segment
21 <span>dw 0123h, 0456h
22 <span>data ends
23
24 <span>stack segment
25   dw 0,0
26 <span>stack ends
27 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>回答教材中①②③三个问题。</p>
</blockquote>
<p>① data段中数据不变,为0123h,&nbsp;0456h。</p>
<p>②&nbsp;cs =&nbsp;076ah, ss =&nbsp;076eh, ds =&nbsp;076dh。</p>
<p>③ data段的段地址为X+3,stack段的段地址为X+4。</p>
<blockquote>
<p>附上回答②时反汇编调试截图,即:在debug中,执行到程序返回前的调试截图。</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121193718807-885551859.jpg"></p>
<h4>6.&nbsp;实验任务6</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(4)</p>
<blockquote>
<p>回答教材中提出的问题,并按要求说明原因。</p>
</blockquote>
<p>若将“end&nbsp;start”改为“end”,则只有task 5可以正确执行。因为修改之后,不指明程序入口,则程序从头开始执行。但是task 3与4开头均为数据段与栈段,这里的数据会被当作机器指令执行,所以无法得到预期的结果;而task 5开头即为代码段,所以从头执行能够得到正确的结果,同时在代码段结束时调用系统中断退出程序,从而能够得到预期的结果。</p>
<h4>7.&nbsp;实验任务7</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(5)</p>
<p><strong>注*: 如果在集成软件环境下编写、汇编这个实验任务,请将段名为c的逻辑段,名称改为c1或别的标识</strong><br><strong>符。由于早期一些指令集中使用c指代寄存器,如不更正,有些汇编器在汇编时会报错。</strong></p>
<blockquote>
<p>附上完整源代码文件task7.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:<span>code
2 <span>a segment
3   db 1,2,3,4,5,6,7,8
4 <span>a ends
5
6 <span>b segment
7   db 1,2,3,4,5,6,7,8
8 <span>b ends
9
10 c1 segment   ; 在集成软件环境中,请将此处的段名称由c→改为c1或其它名称
11   db 8 dup(0<span>)
12 <span>c1 ends
13
14 <span>code segment
15 start:
16   mov<span> ax, a
17   mov<span> ds, ax
18
19   mov cx, 8
20   mov bx, 0
21 s:    mov<span> al,
22   add<span> al,
23   mov<span> , al
24   inc<span> bx
25 <span>    loop s
26
27   mov<span> ah, 4ch
28   int<span> 21h
29 <span>code ends
30 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上在debug环境中,执行到程序返回前,查看逻辑段c的数据的截图,以此验证所编写的程序正确实现了题目要求。</p>
</blockquote>
<p>首先查看相加之前c段中的数据(d 20 2f),可以看出均为0。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121194737055-1357903795.jpg"></p>
<p>反汇编以查看指令地址,并执行至程序退出前,再次查看内存(d 20 2f)。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121194941493-814970804.jpg"></p>
<p>可以看出程序正确执行。</p>
<h4>8.&nbsp;实验任务8</h4>
<p>教材「实验5 编写、调试具有多个段的程序」(6)</p>
<blockquote>
<p>附上完整源代码文件task8.asm</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:<span>code
2
3 ; ds:0
4 <span>a segment
5   dw 1,2,3,4,5,6,7,8,9<span>,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
6 <span>a ends
7
8 ; ds:20h
9 <span>b segment
10   dw 8 dup(0<span>)
11 <span>b ends
12
13 ; ds:30h
14 <span>code segment
15 start:
16   mov<span> ax, a
17   mov<span> ds, ax
18
19   add ax, 2
20   mov<span> ss, ax
21   mov<span> sp, 10h
22
23   mov cx, 8
24   mov bx, 0
25 s:    push<span>
26   add bx, 2
27 <span>    loop s
28
29   mov<span> ah, 4ch
30   int<span> 21h
31 <span>code ends
32 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上在debug环境中,执行到程序返回前,查看逻辑段c的数据的截图,以此验证所编写的程序正确实现了题目要求。</p>
</blockquote>
<p>首先查看栈操作之前b段中的数据(d 20 2f),可以看出均为0。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121195218276-1489639297.jpg"></p>
<p>反汇编以查看指令地址,并执行至程序退出前,再次查看内存(d 20 2f)。</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202011/2175620-20201121195348413-1282329544.jpg"></p>
<p>可以看出程序正确执行。</p>
<h2>实验四</h2>
<h3>四、实验结论</h3>
<h4>1.&nbsp;实验任务1</h4>
<p>教材「实验9 根据材料编程」(P187-189)<br>编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串'welcome to masm!'。</p>
<blockquote>
<p><strong>Tips</strong></p>
<p>这道编程练习需要考虑的两个关键问题:</p>
<ul>
<li>屏幕中间对应的显存位置的计算 —— 第×行第×列对应的显存地址单元</li>
<li>字符串颜色属性的设置</li>
</ul>
<p>上述两个问题,请参考教材188-189或第9章课件,内有:</p>
<ul>
<li>80×25彩色字符模式显示缓冲区结构说明</li>
<li>字符属性字节的设置依据</li>
</ul>
<p>字符串及其颜色属性信息,可以提前定义在数据段中。<br>要显示字符串,本质上,就是把字符及其颜色属性信息,复制到相应的显存空间,借助寻址方式和循环实现。</p>
<p><br>附: 本练习中显示字符串所对应的显存空间偏移地址<br>80×25的彩色字符模式,即一屏25行80列。<br>每一行显示一个字符需要两个字节(低位字节存放字符的ASCⅡ码值,高位字节存放字符的显示属性),一共160个字节。<br>默认,在显存第0列显示时,对应的显存空间为B8000H ~ B8F9FH。如果以B800H作为段地址,则一屏25行对应的偏移地址如下。请据此计算出屏幕中间位置对应的显存地址。</p>
</blockquote>
<p>&nbsp;<img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201225091651123-1336708864.jpg"></p>
<blockquote>
<p>附上源程序代码</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 ; task1.asm
2 assume cs:code, ds:<span>data
3 <span>data segment
4   db 'welcome to masm!', 0
5   color db 2, 24h, 71h    ; store color attributes here
6 <span>data ends
7 <span>code segment
8 start:
9   mov<span> ax, data
10   mov<span> ds, ax
11   mov bx, 720h      ; 11(line)*160(bytes/line)+32(column)*2(bytes/column)
12   mov cx, 3            ; loop 3 times for 3 lines
13   mov di, 0            ; offset of color attributes in color segment
14   mov si, 0
15
16 s:mov ah, color      ; store color attribute in ah, and character in al
17   call print            ; print the string at position es:
18   add bx, 0a0h      ; switch to next line (+160bytes)
19   inc di            ; switch to next color attribute
20 <span>    loop s
21
22   mov<span> ah, 4ch
23   int<span> 21h
24
25 print:
26   push es            ; push registers so that they can be used in subprogram
27   push<span> dx
28   push<span> di
29   push<span> si
30   push<span> ax
31   mov dx, 0b800h      ; video memory
32   mov<span> es, dx
33   mov di, 0
34
35 sprint:    mov al, ds:      ; store color attribute in ah, and character in al
36   cmp al, 0            ; if string ends, then return
37   je<span> ed
38   mov es:, ax    ; print the character
39   inc<span> si
40   add di, 2
41   jmp<span> sprint
42
43 ed: pop<span> ax
44   pop<span> si
45   pop<span> di
46   pop<span> dx
47   pop<span> es
48   ret
49
50 <span>code ends
51 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上运行结果截图</p>
</blockquote>
<p>图不贴了</p>
<h4>2.&nbsp;实验任务2</h4>
<p>编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。</p>
<blockquote>
<p>子程序printSar</p>
<ul>
<li>功能:以指定颜色在屏幕上(从屏幕左上角开始)输出字符串</li>
<li>要求:字符串以0结尾</li>
<li>入口参数
<ul>
<li>字符串的起始地址—&gt; ds: si (其中,字符串所在段的段地址—&gt; ds, 字符串起始地址的偏移地址—&gt; si</li>
<li>字符串颜色—&gt; al</li>
</ul>
</li>
<li>出口参数:无</li>
</ul>
</blockquote>
<p>&nbsp;</p>
<blockquote>
<p>附上源程序代码</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:<span>data
2 <span>data segment
3   str db 'try', 0
4 <span>data ends
5
6 <span>code segment
7 start:
8   mov<span> ax, data
9   mov<span> ds, ax
10
11   mov si, offset str
12   mov al, 2
13   call<span> printStr
14
15   mov<span> ah, 4ch
16   int<span> 21h
17
18 printStr:
19   push<span> bx
20   push<span> cx
21   push<span> si
22   push<span> di
23
24   mov<span> bx, 0b800H
25   mov<span> es, bx
26   mov di, 0
27 s:      mov<span> cl,
28   mov ch, 0
29   jcxz<span> over
30   mov<span> ch, al
31   mov es:<span>, cx
32   inc<span> si
33   add di, 2
34   jmp<span> s
35
36 over:   pop<span> di
37   pop<span> si
38   pop<span> cx
39   pop<span> bx
40   ret
41
42 <span>code ends
43 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上运行结果截图</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212195006996-354160800.jpg"></p>
<p>修改Line3与Line12后运行结果截图:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212195124237-1253775379.jpg"></p>
<blockquote>
<p>line19-22, line36-39,这组对称使用的push、pop,这样用的目的是什么?</p>
</blockquote>
<p>在子程序执行之前将寄存器的数据保存至栈中,子程序执行结束返回之前再将寄存器的数据从栈中恢复,可以保护主程序在栈中存放的数据不被修改。</p>
<blockquote>
<p>line30的功能是什么?</p>
</blockquote>
<p>将要显示的数据移动至显存区域,以在屏幕上显示。</p>
<h4>3.&nbsp;实验任务3</h4>
<blockquote>
<p>子程序num2str:</p>
<ul>
<li>功能:把0~2559之间的任意整数转换成数字字符串,例如,把1984转换成'1984'</li>
<li>入口参数
<ul>
<li>要转换的整数 —&gt; ax</li>
<li>数字字符串的起始地址 —&gt; ds:di (其中:数字字符串所在段的段地址—&gt; ds,字符串起始地址的偏移地址—&gt;di)</li>
</ul>
</li>
<li>出口参数:无</li>
</ul>
</blockquote>
<p>&nbsp;</p>
<blockquote>
<ul>
<li>子任务1</li>
</ul>
<p>对task3.asm进行汇编、链接,得到可执行程序后,在debug中使用u命令反汇编,使用g命令执行到line15(程序退出之前),使用d命令查看数据段内容,观察是否把转换后的数字字符串'1984'存放在数据段中str标号后面的单元。</p>
<ul>
<li>子任务2</li>
</ul>
<p>对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来,实现对转换后的字符串进行输出。</p>
</blockquote>
<p>&nbsp;</p>
<blockquote>
<p>附上子任务1的反汇编截图</p>
</blockquote>
<p>程序运行前首先查看内存,再反汇编</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212200345195-2094939382.jpg"></p>
<p>可以看出此时内存中数据为0,程序结束前的指令地址为076c:000e。使用g命令执行至程序结束前</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212200508107-2051266322.jpg"></p>
<p>可以看出1984被成功存放在数据段中str标号后面的单元。</p>
<blockquote>
<p>附上子任务2修改、完善后的完整汇编源代码,及,运行测试截图</p>
</blockquote>
<p>将task2.asm中的printStr添加至task3.asm后</p>
<div class="cnblogs_code">
<pre> 1 assume cs:code, ds:<span>data
2 <span>data segment
3         x dw 1984
4         str db 16 dup(0<span>)
5 <span>data ends
6
7 <span>code segment
8 start:
9         mov<span> ax, data
10         mov<span> ds, ax
11         mov<span> ax, x
12         mov di, offset str
13         call<span> num2str
14
15         mov si, offset str
16         mov<span> al, 70h
17         call<span> printStr
18
19         mov<span> ah, 4ch
20         int<span> 21h
21
22 num2str:
23         push<span> ax
24         push<span> bx
25         push<span> cx
26         push<span> dx
27         
28         mov cx, 0
29         mov bl, 10
30 s1:      
31         div<span> bl
32         inc<span> cx
33         mov<span> dl, ah
34         push<span> dx
35         mov ah, 0
36         cmp al, 0
37         jne<span> s1
38 s2:      
39         pop<span> dx
40         or<span> dl, 30h
41         mov<span> , dl
42         inc<span> di
43 <span>      loop s2
44         
45         pop<span> dx
46         pop<span> cx
47         pop<span> bx
48         pop<span> ax
49
50         ret
51
52 printStr:
53   push<span> bx
54   push<span> cx
55   push<span> si
56   push<span> di
57
58   mov<span> bx, 0b800H
59   mov<span> es, bx
60   mov di, 0
61 s:      mov<span> cl,
62   mov ch, 0
63   jcxz<span> over
64   mov<span> ch, al
65   mov es:<span>, cx
66   inc<span> si
67   add di, 2
68   jmp<span> s
69
70 over:   pop<span> di
71   pop<span> si
72   pop<span> cx
73   pop<span> bx
74   ret
75 <span>code ends
76 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>运行结果:</p>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212205222860-1017438014.jpg"></p>
<h4>4.&nbsp;实验任务4</h4>
<p>task4.asm中用到的两个系统功能调用<br>int 21h中的1号子功能</p>
<ul>
<li>功能:从键盘输入单个字符</li>
<li>用法:</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">mov</span> ah, <span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> 21h <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 出口参数为al, 从键盘输入的字符保存在al中</span></pre>
</div>
<p>int 21h中的2号子功能</p>
<ul>
<li>功能:向屏幕输出单个字符</li>
<li>用法:</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">mov</span> ah, <span style="color: rgba(128, 0, 128, 1)">2</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span> dl, <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> ××是待输出的字符,或其ASCⅡ码值</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> 21h</pre>
</div>
<blockquote>
<p>附上程序源代码</p>
</blockquote>
<div class="cnblogs_code">
<pre> 1 ; task4.asm
2 assume cs:code, ds:<span>data
3 <span>data segment
4         str db 80<span> dup(?)
5 <span>data ends
6
7 <span>code segment
8 start:
9         mov<span> ax, data
10         mov<span> ds, ax
11         mov si, 0
12
13 s1:      
14         mov ah, 1
15         int<span> 21h
16         mov<span> , al
17         cmp al, '#'
18         je<span> next
19         inc<span> si
20         jmp<span> s1
21 next:
22         mov<span> cx, si
23         mov si, 0
24 s2:   mov ah, 2
25         mov<span> dl,
26         int<span> 21h
27         inc<span> si
28 <span>      loop s2
29
30         mov<span> ah, 4ch
31         int<span> 21h
32 <span>code ends
33 end start</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<blockquote>
<p>附上运行测试截图</p>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/2175620/202012/2175620-20201212210242702-2141155119.jpg"></p>
<blockquote>
<p>line13-20实现的功能是?</p>
</blockquote>
<p>从键盘中读取字符存入data&nbsp;segment中,直到遇到'#'结束。</p>
<blockquote>
<p>line22-28实现的功能是?</p>
</blockquote>
<p>将用户输入的串在屏幕上打印。</p>
<h4>5.&nbsp;实验任务5</h4>
<div class="cnblogs_code">
<pre> 1 // task5.c
2 #include &lt;stdio.h&gt;
3
4 int sum(int, int<span>);
5
6 int<span> main() {
7   int a = 2, b = 7<span>, c;
8   c =<span> sum(a, b);
9   return 0<span>;
10 <span>}
11
12 int sum(int x, int<span> y) {
13   return (x +<span> y);
14 }</span></span></span></span></span></span></span></span></pre>
</div>
<p>由于我的电脑上未安装Visual&nbsp;Studio环境,下面使用gcc环境进行反汇编等操作。使用gcc命令进行编译得到task5.o文件,然后使用objdump命令进行反汇编。</p>
<div class="cnblogs_code">
<pre>(base) PS D:\&gt; gcc -g -<span>c task5.c
(base) PS D:\&gt; objdump -d -M intel -S task5.o &gt;&gt; task5.s</span></pre>
</div>
<p>使用这种方式得到的.s文件同时包含.c文件源代码以及反汇编指令代码,阅读起来较为方便,使用以下命令同样也可以进行反汇编,但是得到的.s文件仅有反汇编指令代码。</p>
<div class="cnblogs_code">
<pre>gcc -S task5.c</pre>
</div>
<p>查看task5.s中的内容</p>
<div class="cnblogs_code">
<pre> 1 task5.o:<span>   file format pe-i386
2
3
4 Disassembly of section .text:
5
6 00000000<span> &lt;_main&gt;:
7 <span>// task5.c
8 <span>#include &lt;stdio.h&gt;
9
10 int sum(int, int);
11
12 int<span> main() {
13    0:    55                     push<span>   ebp
14    1:    89 e5                  mov<span>    ebp,esp
15    3:    83 e4 f0               and<span>    esp,0xfffffff0
16    6:    83 ec 20               sub<span>    esp,0x20
17    9:    e8 00 00 00 00         call<span>   e &lt;_main+0xe&gt;
18   int a = 2, b = 7, c;
19    e:    c7 44 24 1c 02 00 00   mov<span>    DWORD PTR ,0x2
20   15:    00
21   16:    c7 44 24 18 07 00 00   mov<span>    DWORD PTR ,0x7
22   1d:    00
23   c = sum(a, b);
24   1e:    8b 44 24 18            mov<span>    eax,DWORD PTR
25   22:    89 44 24 04            mov<span>    DWORD PTR ,eax
26   26:    8b 44 24 1c            mov<span>    eax,DWORD PTR
27   2a:    89 04 24               mov<span>    DWORD PTR ,eax
28   2d:    e8 0b 00 00 00         call<span>   3d &lt;_sum&gt;
29   32:    89 44 24 14            mov<span>    DWORD PTR ,eax
30   return 0;
31   36:    b8 00 00 00 00         mov<span>    eax,0x0
32 <span>}
33   3b:    c9                     leave
34   3c:    c3                     ret   
35
36 0000003d<span> &lt;_sum&gt;:
37
38 int sum(int x, int<span> y) {
39   3d:    55                     push<span>   ebp
40   3e:    89 e5                  mov<span>    ebp,esp
41   return (x + y);
42   40:    8b 55 08               mov<span>    edx,DWORD PTR
43   43:    8b 45 0c               mov<span>    eax,DWORD PTR
44   46:    01 d0                  add<span>    eax,edx
45   48:    5d                     pop<span>    ebp
46   49:    c3                     ret   
47   4a:    90                     nop
48   4b:    90                     nop</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<ul>
<li>参数传递:Line24-27可以看出在调用sum子函数前,main函数将两个参数放在了栈顶上方,即与,在sum子函数里,再从与处取得。这里猜测是调用sum函数时,将CS与EIP压入了栈中,所以ESP减小了0x8。</li>
<li>返回值传递:Line29与Line44可以看出返回值存放在EAX寄存器中。</li>
<li>参数顺序:比较Line19-21与Line24-27可以看出,在调用c=sum(a, b)时,b首先被存至栈顶上方一个int处,接着a再被存至栈顶处。所以参数的处理顺序为从右至左。</li>
</ul><br><br>
来源:https://www.cnblogs.com/xywei0905/p/14187360.html
頁: [1]
查看完整版本: 汇编语言实验总结