复习王爽《汇编语言》5-8章:
此实验任务中,包含4个子任务。逐一实践,结合实践观察、验证,回答问题。
assume ds:data, cs:code, ss:stack data segment db 16 dup(0) ; 预留16个字节单元,初始值均为0 data ends stack segment db 16 dup(0) ;预留16个字节单元,初始值均为0 stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 16 ; 设置栈顶 mov ah, 4ch int 21h code ends end start
① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076B, 寄存器(CS) =076C
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-2, stack的段地址是 X-1。
内存按照代码中数据、代码段书写顺序自上而下分配,故先分配data段再分配stack段最后分配code段,一个段地址长度为16字节,故两个数据段各分配1个段地址长度,为X-2和X-1。以下子任务类似。
assume ds:data, cs:code, ss:stack data segment db 4 dup(0) ; 预留4个字节单元,初始值均为0 data ends stack segment db 8 dup(0) ; 预留8个字节单元,初始值均为0 stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 8 ; 设置栈顶 mov ah, 4ch int 21h code ends end start
① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076B, 寄存器(CS) =076C
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-2, stack的段地址是 X-1。
数据段不足16字节也分配满16字节。8086内存分配一般以16字节为单位。
assume ds:data, cs:code, ss:stack data segment db 20 dup(0) ; 预留20个字节单元,初始值均为0 data ends stack segment db 20 dup(0) ; 预留20个字节单元,初始值均为0 stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 20 ; 设置初始栈顶 mov ah, 4ch int 21h code ends end start
① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076a, 寄存器(SS) =076C, 寄存器(CS) =076E
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X-4, stack的段地址是 X-2。
assume ds:data, cs:code, ss:stack code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 20 mov ah, 4ch int 21h code ends data segment db 20 dup(0) data ends stack segment db 20 dup(0) stack ends end start
① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) =076C, 寄存器(SS) =076E, 寄存器(CS) =076A
② 假设程序加载后,code段的段地址是X,则,data段的段地址是 X+2, stack的段地址是 X+4。
该任务code段位于开头故data段和stack段地址在后。
① 对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是[N/16]*16 (中括号是向上取整)
xxx segment db N dup(0) xxx ends
② 如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start
改成end
, 哪一个程序仍然可以正确执行?结合实践观察得到的结论,分析、说明原因。
第四个任务依旧能够成功运行。其他三个任务再更改末尾的end start后,start伪指令失效,程序从段前缀起始依次向后执行,根据分配次序前三个任务有数据段打头,程序无法识别代码类别产生错误,第四个任务代码段最先分配规避了冲突的产生。
编写一个汇编源程序,实现向内存单元b800:0f00 ~ b800:0f9f连续160字节,依次重复填充十六进制数据03 04。
Tips:
在debug中,使用f命令,向内存单元批量填写数据。 -f b800:0f00 0f9f 03 04 把内存单元区间b800:0f00 ~ b800:0f9f连续160个字节,依次重复填充十六进制数据03 04。
程序代码:
assume cs:code code segment start: mov ax,0b800h mov ds,ax mov bx,0f00h mov cx,80 p: mov ds:[bx],0403h add bx,2 loop p mov ah,4ch int 21h code ends end start
结果如图
已知8086汇编源程序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 cx,16 mov bx,0 s: mov al,ds:[bx] add al,ds:[bx+16] mov ds:[bx+32],al inc bx loop s mov ah, 4ch int 21h code ends end start
data1和data2各存有10个10进制数,为其分配16字节空间,所以data1数据段对应data2数据段的位置为data1+16,对应data3的位置为data1+32。据此写出此三步代码
mov al,ds:[bx]
add al,ds:[bx+16]
mov ds:[bx+32],al
完成对应位置数相加后的保存。
实验结果:
已知8086汇编源程序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
要求:
① 补全程序,实现把逻辑段data1中的8个字数据逆序存储到逻辑段b中。
② 汇编、连接后,在debug中加载程序,运行到line15程序退出前,使用d命令查看数据段data2对应的内存空间,确认是否实现题目要求。
补全后代码:
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,stack mov ss,ax mov sp,16 mov bx,0 mov cx,8 s1: push ds:[bx] add bx,2 loop s1 mov bx,16 mov cx,8 s2: pop ds:[bx] add bx,2 loop s2 mov ah, 4ch int 21h code ends end start
利用栈依次压入8个数再依次弹出到data2对应位置,注意弹出时bx值的设置。
实验结果:
使用任意文本编辑器,录入汇编源程序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,循环实现的功能是什么,逐行理解每条指令的功能。
db 2,3,4,5,6 --> 改成: db 5 dup(2) 或 db 5 dup(5)
基于观察,分析、猜测这里的数值作用是什么。
1.运行结果
2.运行结果
3.line19的作用是将小写字母转换为大写字母,实现方式基于英文大小写字母ASCII码的特性,小写字母比对应大写字母高32,可以利用二进制数相与改变对应位的数值,相与的二进制数在想要赋0的位置填充0,其余位填充1,可以达到一种“二进制掩码”的效果。
4.运行结果
5个数值依次对应5个字母的字体颜色。
已知8086汇编源程序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段中的每行第一个单词从大写->小写。
② 在debug中加载程序,反汇编,执行到line13退出前,用d命令查看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 cx,4 mov bx,0 s: mov dx,cx mov cx,4 mov si,0 p: mov al,ds:[bx+si] or al,00100000B mov ds:[bx+si],al inc si loop p add bx,16 mov cx,dx loop s mov ah, 4ch int 21h code ends end start
实验结果:
外层循环遍历4行单词,内存循环遍历首单词的每个字母,利用dx暂存cx值。通过or指令将单词数据与00100000B相或得到ASCII更大的小写字母。
问题场景描述:
Power idea公司1975年-1979年的基本情况如下:
程序task7.asm的逻辑段data中(line4-6),已经定义好了这些数据。
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段中。
表格中,每行数据,在逻辑段table中占16个字节,各项数据占据字节大小分配如下。期中,数据之间用空格间隔。
② 汇编、连接后,在debug中加载、调试程序。灵活、合理使用u命令、g命令、d命令,显示刚开始逻辑段table的数据信息,以及,结构化存入数据后,数据段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 si,0 mov di,0 mov bx,0 mov cx,5 mov sp,0 s: mov ax,[si] mov es:[di],ax mov ax,[si+2] mov es:[di+2],ax mov ax,[bx+20] mov es:[di+5],ax mov dx,0 mov es:[di+7],dx push cx mov cx,[20+10+bx] mov es:[di+10],cx div cx pop cx mov es:[di+0dh],ax add si,4 add di,16 add bx,2 loop s mov ah, 4ch int 21h code ends end start
实验结果: