实验2 多个逻辑段的汇编源程序编写与调试
Posted 余|山
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实验2 多个逻辑段的汇编源程序编写与调试相关的知识,希望对你有一定的参考价值。
原因:实际上伪指令end 描述了程序的结束和程序的入口。在编译、连接后,"end start" 指明的程序入口,被转化为一个入口地址,存储在可执行文件的描述信息中。当把start去掉之后程序入口转换成一开始默认的076A,而task1_1,task1_2,task1_3的真正程序段入口不为076A导致程序在内存空间中无法找到正确的指令。
assume cs:code code segment start: mov ax, 0b800h mov ds, ax mov bx, 0f00h mov cx, 50h s: mov ds:[bx], 0403h add bx, 2 loop s mov ah, 4ch int 21h code ends end start
(问题)
debug执行程序后,用d指令访问内存单元发现并未填入内存
编程实现时,注意进制问题、字节顺序问题。编写后,运行程序,如果与实验1的实验任务3结果不一致,说明程序编写有错误。
assume cs:code data1 segment db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers data1 ends data2 segment db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers data2 ends data3 segment db 16 dup(0) data3 ends code segment start: mov ax,data1 mov ds,ax mov bx,0 mov cx 0ah s:mov ax,ds:[bx] add ax,ds:[bx+10h] mov ds:bx[bx+20],ax inc bx loop s mov ah,4ch int 21h code ends end start
结果:
assume cs:code, ss:stack
data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends
data2 segment
dw 8 dup(0)
data2 ends
stack segment
dw 8 dup(0)
stack ends
code segment
start:
mov ax, data1
mov ds, ax
mov bx, 0
mov cx, 8
mov sp, 9
s1: push ds:[bx]
add bx, 2
loop s1
mov ax, data2
mov ds, ax
mov bx, 0
mov cx, 8
s2: pop ds:[bx]
add bx, 2
loop s2
mov ah, 4ch
int 21h
code ends
end start
实验结果:
db 2,3,4,5,6 --> 改成: db 5 dup(2) 或 db 5 dup(5)
经过分析应该是修改颜色。
assume cs:code, ds:data data segment db \'Pink Floyd \' db \'JOAN Baez \' db \'NEIL Young \' db \'Joan Lennon \' data ends code segment start: mov ax, data mov ds, ax mov cx, 64 mov bx, 0 mov ax,20h s: or [bx], ax inc bx loop s mov ah, 4ch int 21h mov ah, 4ch int 21h code ends end start
assume cs:codesg data segment db \'1975\', \'1976\', \'1977\', \'1978\', \'1979\' dd 16, 22, 382, 1356, 2390 dw 3, 7, 9, 13, 28 data ends table segment db 5 dup( 16 dup(\' \') ) table ends codesg segment start: mov ax, data mov ds, ax mov ax, table mov es, ax mov bx, 0 mov bp, 0 mov cx, 5 ;年份 s: mov dx, cx mov cx, 4 mov si, 0 s1: mov al, ds:[bx+si] mov es:[bp+si], al inc si loop s1 mov cx, dx mov byte ptr es:[bp+4],\' \' add bx, 4 add bp, 10h loop s mov bp, 0 mov cx, 5 ;收入 s2: mov ax,ds:[bx] mov es:[bp+5],ax mov ax,ds:[bx+2] mov es:[bp+7],ax mov byte ptr es:[bp+9], \' \' add bx, 4 add bp, 10h loop s2 mov bp, 0 mov cx, 5 ;雇员 s3: mov ax, ds:[bx] mov es:[bp+0ah], ax mov byte ptr es:[bp+0ch], \' \' add bx, 2 add bp, 10h loop s3 mov bp,0 mov cx,5 ;人均 s4: mov ax, es:[bp+5] mov dx, es:[bp+7] div word ptr es:[bp+0ah] mov es:[bp+0dh], ax mov byte ptr es:[bp+0fh], \' \' add bp, 10h loop s4 mov ax, 4c00h int 21h codesg ends end start
实验2 多个逻辑段的汇编源程序编写与调试
实验任务1_1
① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A___, 寄存器(SS) =_076B_, 寄存器(CS) = 076C
② 假设程序加载后,code段的段地址是X,则,data段的段地址是_X-2H_, stack的段地址是_X-1H_
由于data段、stack段刚好各分配了16B的单位,而系统为段内存分配都是以16B为单位分配的,由于物理地址 = 段地址 × 16 + 偏移地址,因此相隔16B正好段地址相差1H
实验任务1_2
1在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A___, 寄存器(SS) =_076B___, 寄存器(CS) = _076C___
2假设程序加载后,code段的段地址是X,则,data段的段地址是_X-2H_, stack的段地址是_X-1H_
由于data段、stack段刚好各分配了16B的单位,而系统为段内存分配都是以16B为单位分配的,由于物理地址 = 段地址 × 16 + 偏移地址,因此相隔16B正好段地址相差1H
实验任务1_3
1.在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A___, 寄存器(SS) =_076C___, 寄存器(CS) = _076E___
2.假设程序加载后,code段的段地址是X,则,data段的段地址是X-4H_, stack的段地址是X-2H_
实验任务1_4
1.在debug中将执行到line9结束、line11之前,记录此时:寄存器(DS) = _076C___, 寄存器(SS) =_076E___, 寄存器(CS) = _076A___
2 .假设程序加载后,code段的段地址是 X_,则,data段的段地址是_X+2H_, stack的段地址是X+4H_
实验任务1_5
基于上述四个实验任务的实践、观察,总结并回答:
1 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 16Byte
xxx segment db N dup(0) xxx ends
2 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成end , 哪一个程序仍然可以正确执行?结合实践观察得到的结论,分析、说明原因。
Task1_4.asm任然可以正常运行
原因:end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方。在程序6.2中我们用end指令指明了程序的入口在标号start处。
尾指令end 描述了程序的结束和程序的入口。在编译、连接后,"end start" 指明的程序入口,被转化为一个入口地址,存储在可执行文件的描述信息中。
实验任务二
编写一个汇编源程序,实现向内存单元b800:0f00 ~ b800:0f9f连续160字节,依次重复填充十六进制数
据03 04。
Tips:
1. 在实验1的实验任务3中,做过达到同样效果的实验。但当时是通过debug的f命令实现填充的。这一次,要求编程实现。
在debug中,使用f命令,向内存单元批量填写数据。
-f b800:0f00 0f9f 03 04 把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04。
2. 编程实现时,注意进制问题、字节顺序问题。编写后,运行程序,如果与实验1的实验任务3结果不一致,说明程序编写有错误。
使用debug f命令把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04结果如下
编程实现代码如下:
assume cs:code code segment start: mov ax, 0b800h mov ds, ax mov bx, 0f00h mov cx, 50h mov ax, 0403h s: mov ds:[bx], ax add bx, 2 loop s mov ah, 4ch int 21h code ends end start
通过编译连接运行编写的task2.asm,可以看到编程方式实现也达到了同样的效果。
实验任务三
已知8086汇编源程序task3.asm代码片段如下。
task3.asm
assume cs:code data1 segment db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers data1 ends data2 segment db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers data2 ends data3 segment db 16 dup(0) data3 ends code segment start: ; ××× mov ah, 4ch int 21h code ends end start
要求:
① 编程实现把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中。
② 在debug中加载、反汇编、调试。在数据项依次相加前,和相加后,分别查看三个逻辑段data1,
data2, data3对应的内存空间,确认逐一相加后,结果的确保存在了逻辑段data3中。
完整代码:
assume cs:code data1 segment db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers data1 ends data2 segment db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers data2 ends data3 segment db 16 dup(0) data3 ends code segment start: mov ax, data1 mov ds, ax mov bx, 0 mov cx, 10 s: mov ax, [bx] add ax, [bx+16] mov [bx+32], ax inc bx loop s mov ah, 4ch int 21h code ends end start
反汇编:
运行前后内存单元内容对比
可以看到实现了逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中。
实验任务四
已知8086汇编源程序task4.asm代码片段如下。
task4.asm
assume cs:code data1 segment dw 2, 0, 4, 9, 2, 0, 1, 9 data1 ends data2 segment dw 8 dup(?) data2 ends code segment start: ; ××× mov ah, 4ch int 21h code ends end start
要求:
1. 补全程序,实现把逻辑段data1中的8个字数据逆序存储到逻辑段b中。
完整代码:
assume cs:code data1 segment dw 2, 0, 4, 9, 2, 0, 1, 9 data1 ends data2 segment dw 8 dup(?) data2 ends code segment start: mov ax, data1 mov ds, ax mov ax, data2 mov es, ax mov ss, ax mov sp, 32 mov bx, 0 mov cx, 8 s1: push [bx] add bx, 2 loop s1 mov bx,16 mov cx, 8 s2: pop [bx] add bx, 2 loop s2 mov ah, 4ch int 21h code ends end start
2.汇编、连接后,在debug中加载程序,运行到line15程序退出前,使用d命令查看数据段data2对应的内存空间,确认是否实现题目要求。
可以看到运行前data2中为全0,运行后data2中为data1的逆序,成功实现。
实验任务五
使用任意文本编辑器,录入汇编源程序task5.asm。
assume cs:code, ds:data data segment db \'Nuist\' db 2, 3, 4, 5, 6 data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
阅读源程序,从理论上分析源代码的功能,尤其是line15-25,循环实现的功能是什么,逐行理解每条指令的功能。
对程序进行汇编、链接,得到可执行文件,运行并观察结果。
汇编链接运行观察实现结果,屏幕上显示出彩色的NUIST字样
使用debug工具对程序进行调试,执行到程序返回前,即line25执行之后、line27执行之前,观察结果
源代码中line19的作用是?
进行相与运算,结果-32,即把大写字母转化为小写字母
修改line4里5个字节单元的值,重新汇编、链接、运行,观察结果。
db 2,3,4,5,6 --> 改成: db 5 dup(2)
db 2,3,4,5,6 --> 改成: db 5 dup(5)
基于观察,分析、猜测这里的数值作用是什么?
Line 4的内容的用途:8位色彩代码用来控制输出颜色。
实验任务六
已知8086汇编源程序task6.asm代码片段如下。
task6.asm
assume cs:code, ds:data data segment db \'Pink Floyd \' ; 16字节 db \'JOAN Baez \' ; 16字节 db \'NEIL Young \' ; 16字节 db \'Joan Lennon \' ; 16字节 data ends code segment start: ; ××× mov ah, 4ch int 21h code ends end start
要求:
补全程序,将data段中的每行第一个单词从大写->小写。
完整代码:
assume cs:code, ds:data data segment db \'Pink Floyd \' db \'JOAN Baez \' db \'NEIL Young \' db \'Joan Lennon \' data ends code segment start: mov ax, data mov ds, ax mov bx, 0 mov cx, 4 s: mov ax, [bx] or ax, 20h mov [bx], ax add bx, 16 loop s mov ah, 4ch int 21h code ends end start
在debug中加载程序,反汇编,执行到line13退出前,用d命令查看data段对应的内存空间,确认每行第一个单词已经由大写->小写。
反汇编
成功实现data段对应的内存空间每行第一个单词由大写转化为小写。
实验任务七
问题场景描述:
Power idea公司1975年-1979年的基本情况如下:
程序task7.asm的逻辑段data中(line4-6),已经定义好了这些数据。
task7.asm
assume cs:code, ds:data, es:table data segment db \'1975\', \'1976\', \'1977\', \'1978\', \'1979\' dw 16, 22, 382, 1356, 2390 dw 3, 7, 9, 13, 28 data ends table segment db 5 dup( 16 dup(\' \') ) ; table ends code segment start: mov ah, 4ch int 21h code ends end start
要求:
① 补全程序,实现题目要求,把年份、收入、雇员人数、人均收入,以结构化方式写入table段中。
完整代码:
assume cs:code, ds:data, es:table data segment db \'1975\', \'1976\', \'1977\', \'1978\', \'1979\' dw 16, 22, 382, 1356, 2390 dw 3, 7, 9, 13, 28 data ends table segment db 5 dup( 16 dup(\' \') ) ; table ends code segment start: mov ax, data mov ds, ax mov ax, table mov es, ax mov bx, 0 mov bp, 0 mov cx, 5 years: mov ax, ds:[bx] mov es:[bp], ax mov ax, ds:[bx+2] mov es:[bp+2], ax add bx, 4 add bp, 10h loop years mov bp, 5 mov cx, 5 income: mov ax, ds:[bx] mov es:[bp], ax add bx, 2 add bp, 10h loop income mov cx, 5 mov bp, 10 people: mov ax, ds:[bx] mov es:[bp], ax add bx, 2 add bp, 10h loop people mov cx, 5 mov bp, 5 average: mov ax, es:[bp] mov bl, es:[bp+5] div bl mov es:[bp+8], al add bp,10h loop average mov ah, 4ch int 21h code ends end start
表格中,每行数据,在逻辑段table中占16个字节,各项数据占据字节大小分配如下。期中,数据之间用空格间隔。
② 汇编、连接后,在debug中加载、调试程序。灵活、合理使用u命令、g命令、d命令,显示刚开始逻辑段table的数据信息,以及,结构化存入数据后,数据段table的数据信息,确认实现题目要求。
所有数据都已完整、准确存入表中。
以上是关于实验2 多个逻辑段的汇编源程序编写与调试的主要内容,如果未能解决你的问题,请参考以下文章