■ 一个段中数据不满16字节则占用16字节,满16字节不满32字节则占用32字节,反正1-16字节占16字节.
■ start 标号 end start 标明程序的入口
start: mov bx,0 即加载程序时CS:IP指向程序的第一条要执行的指令是"mov bx,0"
■ 我们在描述dw的作用时,可以说用它定义数据也可以说用它开辟内存空间
■ [dw 0 1 2]定义字型数据,内存显示00 00 01 00 02 00 , [db 1 2]定义字节型数据,内存显示01 02
程序取得所需空间的方法有两种:一是在加载程序的时候为程序分配,二是程序在执行过程中向系统申请.
若要一个程序在被加载时候取得所需空间则必须在源程序中做出说明,通过源程序中定义段来进行内存空间的获取
(1)在一个段中存放数据\代码\栈,体会下不使用多个段时的情况
(2)将数据\代码\栈 放入不同的段中
在代码段中使用数据:_________ [dw 0123H,0456H,0789H,0abch,0defh] 定义字型数据dw即"define word"
■□ 定义5个字型数据所占内存空间为10个字节,程序运行时CS中存放代码段的段地址,由于它们在代
码段中,所以可以从CS中得到它们的段地址,因为用dw定义的数据处于代码段的最开始,所以偏移
地址为0,5个数据在代码段的偏移0\2\4\6…处,程序运行时,它们的地址就是cs:0\cs:2\cs:\4…
程序中bx存放加2递增的偏移地址用循环来进行累加,设置(bx)=0指向第一个数据所在字单元,每
次循环中 (bx)=(bx)+2,cs:bx指向下一个数据所在的字单元.
■ assume cs:code
code segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h ;定义字型数据
mov bx,0
mov ax,0
mov cx,8
s: add ax,cs:[bx] ;(ax)=(ax)+((cs)×16+(bx)) 字型数据两个单元,
add bx,2 ;所以要加2,字单元(0,1)(2,3)…分别代表定义的第1\2\…个数据
loop s
mov ax,4c00h
int 21h
code ends
end
□■ 指令[d cs:0]查看程序中前16个字节(8个字单元数据)的内容,
□■ 指令[u cs:10]查看程序总会拿高薪要执行的机器指令(在数据的后面16个字节为F的后面是10H)
怎样执行程序中的指令?用Debug加载后可以将IP设置为10H,从而使CS:IP指向程序的第一条指令
在用[T]或[P]或[G]命令执行.
■■■ 在源程序中指明程序的入口所在:
| assume cs:code
| code segment
| dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
| start: mov bx,0 ;标号"start" ,程序入口指向这条指令,偏移地址部分为10H
| mov ax,0 ;dw定义数据占用了16个字节 第17个单元位置即10H
| mov cx,8
| s: add ax,cs:[bx]
| add bx,2
| loop s
| mov ax,4c00h
| int 21h
| code ends
| end start ;end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方
以上指令指明了程序的入口在标号start处,也就是说"mov bx,0"是程序的第一条指令
■ 根据什么设置CPU的cs:ip指向程序入口? 由可执行文件中的描述信息指明.
可执行文件由描述信息和程序组成,程序来自于源程序中的汇编指令和定义的数据;描述信息则
主要是编译\连接程序对源程序中相关伪指令进行处理所得到的信息,以上用伪指令描述了程序的
结束和程序的入口,在编译\连接后,由"end start"指明程序的入口,被转化为一个入口地址,存储
在可执行文件的描述信息中,以上源程序的入口地址偏移部分为:10H,程序被加载入内存后,加载
者从可执行文件的描述信息中读到程序的入口地址,设置CS:IP.
■■■ 若要CPU从何处开始执行程序,只要在源程序中用"end 标号"指明就可以了.
| assume cs:code
| code segment
| ;
| 数据
| start:
| 代码
| ;
| code ends
| end start
在代码段中使用栈:_________ 利用栈将程序中定义的火速据逆顺序存放
assume cs:codesg
codesg segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
?
codesg ends
end
□ 数据存放在cs:0-cs:f单元中,共8个字单元,依次入栈8个单元数据,再依次出栈,实现逆顺序存放
| assume cs:codesg
| codesg segment
| dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
| dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
| ;用ds定义16个字型数据,在程序加载后
| ;将取得16个字的内存空间,存放这16个数据
| ;在后面的程序中将这段空间当作栈来使用
| start: mov ax,cs
| mov ss,ax
| mov sp,30h ;将设置栈顶ss:sp指向cs:30
| ;为什么是30? 因为dw定义了30个字节数据
| mov bx,0
| mov cx,8
| s: push cs:[bx]
| add bx,2
| loop s ;以上将代码段0-15单元中的8个字型数据依次入栈
| mov bx,0
| mov cx,8
| s0: pop cs:[bx]
| add bx,2
| loop s0 ;以上依次出栈8个字型数据到代码段0-15单元中
| mov ax,4c00h
| int 21h
| codesg ends
| end start ;指明程序的入口在start处
我们要将cs:10-cs:2f的内存空间当作栈来用,初始状态下栈为空,所以ss;sp要指向栈底,则设置
ss:sp指向cs:30.
代码段中定义了16个字型数据数值为0,程序加载后将用32个字节的内存空间来存放它们,这段空
间是我们所需要的,程序将它用做栈空间.
■我们在描述dw的作用时,可以说用它定义数据也可以说用它开辟内存空间
____________________________________________________________________________________________________
■ 下面程序实现依次用内存0:0-0:15单元中的内容改写程序中的数据
assume cs:codesg
codesg segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
start: mov ax,0
mov ds,ax
mov bx,0
mov cx,8
s: mov ax,[bx]
(mov cs:[bx],ax) ;cs:[bx]为程序数据所在,ax在上一句赋值了单元0-15[bx]数据所在
add bx,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
■ 下面程序依次用…0:0-0:15内容……改写程序中的数据,数据的传送用栈来进行.栈空间设置在程序内
assume cs:codesg
codesg segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
dw 0,0,0,0,0,0,0,0,0,0 ;10个字单元用作栈空间即20个字节型单元
start: mov ax,(CS)
mov ss,ax ;两次dw定义了0:0-0:23的数据 则空栈的SP的栈底为0:24
mov sp,(24H) ;或 mov sp,36
mov ax,0
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
(pop ss:[bx]) ;实际上就是把push入SS:SP处的数据POP到SS:0000\SS:0002\SS:0004
add bx,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
____________________________________________________________________________________________________
将数据\代码\栈放入不同的段:__________
assume cs:code,ds:data,ss:stack ;定义代码\数据\栈段
data segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
data ends
stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,20h ;设置栈顶ss:sp指向stack:20
mov ax,data
mov ds,ax ;ds指向data段
mov bx,0 ;ds:bx指向data段中的第一个单元
mov cx,8
s: push[bx]
add bx,2
loop s ;以上将data段中的0-15单元中的8个字型数据依次入栈
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0 ;以上依次出栈8个字型数据到data段的0-15单元中
mov ax,4c00h
int 21h
code ends
end start
在程序中,段名相当于一个标号,它代表段地址,所以"mov ax,data"的含义就是将名称为"data"的
段的段地址送入ax.一个段中的数据的段地址可由段名代表,偏移地址要看它在段中的位置.
□ 程序中"data"段中的数据"0abch"的地址就是:data:6 要将它送入bx中就要用以下代码:
mov ax,data 不能用: mov ds,data
mov ds,ax mov bx,ds:[6]
mov bx,ds:[6]
错误指令"mov ds,data",因为8086CPU不允许将一个数值直接送入段寄存器中,程序中对段名的引
用"data"将被编译器处理为一个表示段地址的数值.
□ 代码\数据\栈段完全是我们的安排:
| 定义的段CPU并不会去执行code段的内容,处理data段的数据,将stack当做栈,仅仅当作类似标号.
| 在源程序中用伪指令"assume cs:code,ds:data,ss:stack"将cs\ds\ss分别与code\data\stack段
| 相连,这样作CPU也不会将cs指向code,de指向data,这些都是仅在源程序中存在的信息,CPU不知道
| 通过end start设置程序入口,让CS:IP指向入口执行第一条指令,■"start"在"code"段中,这样
| CPU就将code 段中的内容当作指令来执行了,使用[mov ax,stack mov ss,stack mov sp,20h]来
| 设置ss指向stack,ss:sp指向stack:20,CPU执行这些指令后将把stack段当作栈空间使用,CPU若要
| 访问data段中的数据则可用ds指向data段,用其他寄存器(如bx)来存放data段中数据的偏移地址.
CPU处理我们定义段中的内容当作(指令执行,数据访问,栈空间)通过对CS:IP\SS\DS等寄存器设置
assume cs:b,ds:a,ss:c
a segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
a ends
c segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
c ends
b segment
d: mov ax,c
mov ss,ax
mov sp,20h ;希望用c段当作栈空间,设置ss:sp指向c:20
mov ax,a
mov ds,ax ;希望用ds:bx访问a段中的数据ds指向a段
mov bx,0 ;ds:bx指向a段中的第一个单元
mov cx,8
s: push[bx]
add bx,2
loop s ;以上将a段中的0-15单元中的8个字型数据依次入栈
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0 ;以上依次出栈8个字型数据到data段的0-15单元中
mov ax,4c00h
int 21h
b ends
end d ;d 处是要执行的第一条指令,即程序入口
____________________________________________________________________________________________________
编写\调试具有多个段的程序(1) 将下面程序编译连接,用debug加载\跟踪,回答问题?
assume cs:code,ds:data,ss:stack ;定义代码\数据\栈段
data segment
dw 0123H,0456H,0789H,0abch,0defh,0fedh,0cbah,0987h
data ends
;■ 每个段所占空间为65536 即 0000:0000-0001:0000,如果data段的段地址为076A
; 一个段的容量不能大于64KB即(65536字节)
;■ 则stack段的段则为076B,code段为076C,段名所在的段地址顺序由指令执行顺序安排
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:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00h
int 21h
code ends
end start
(1)cpu执行程序,程序返回前,data段中的数据为多少? 不变
■ (2)程序返回前,cs=?ss=?ds=? ????? cs=076cH ss=076bH ds=076aH
(3)程序加载后,code段的段地址为X,则data 的段地址为?stack段的段地址为?data=X-12H stack=X-2H
___________________________________以下加载编译跟踪后回答问题?
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h
data ends
stack segment
dw 0,0
stack ends
code segment
start: mov ax,stack ;ax=stack段的段地址
mov ss,ax ;ss指向stack段
mov sp,16
mov ax,data
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00h
int 21h
code ends
end start
(1) data段中数据为23 01 56 04 (2)cs=076CH ss=076bH ds=076aH (3)data=X-12H stack=X-2H
(4)段中数据占N字节,则程序加载后该段实际占有空间为? (n+15)/16 或 (取整(N/16)+1)*16
______________________________以下加载编译跟踪后回答问题?
assume cs:code,ds:data,ss:stack
code segment
start: mov ax,stack ;ax=stack段的段地址
mov ss,ax
mov sp,16
mov ax,data
mov ds,ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax,4c00h
int 21h
code ends
data segment
dw 0123h,0456h
data ends
stack segment
dw 0,0
stack ends
end start
(1)21 01 56 04
(2)CS=076AH SS=076EH DS=076DH
(3)data=X-10H stack=X-10H ()
(4)如果将1,2,3题最后一条伪指令"end start"改为"end"(不指明程序入口),则哪个程序仍可以正确执行?
第三个程序可以正常运行,因为前两个程序都未制定程序的入口,而程序的第一部分为数据,即非
程序,当程序被加载入内存时,cs:ip指向这些数据,并当作指令来执行,这样可能会引发意想不到
的后果,而第3个程序cs:ip指向程序第一条指令,因为数据段定义在程序末尾,so程序可正常执行
(5)编写code段中代码,将a段和b段中数据依次相加,结果存C段中:
assume cs:code
a segment
db 1,2,3,4,5,6,7,8 ;定义字节型数据 (内存中会显示 01 02 03 04)而不是00 01 00 02
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,b
mov es,ax
mov bx,0
mov di,0
mov cx,8
mov ax,0
s: mov al,[bx] ;单个单元相加必须用字节型寄存器
add al,es:[bx] ;或者 add al,[bx+16] ,16为十进制
;a段数据在 076A:0 - FH□b段数据在 076B:0 -FH 或是076A:10-1FH,即bx+16 ■c段地址则为076A:20-2F□bx+32
mov [bx+32],al ; bx=1时 ,为ax段:1 ,bx+32 就是 33,就是ax段+2:1 ,如果ax段为1,则cx为3
inc bx
loop s
mov ax,4c00h
int 21h
)
code ends
end start
_____________________________________(6)push a段前八个字型数据,逆序存储到b段
assume cs:code
a segment
dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
;内存显示 01 00 02 00 03 00 ,因为0001H入到内存是01 00 低位对低位
a ends
b segment
dw 0,0,0,0,0,0,0,0
b ends
code segment
start:
(
mov ax,a
mov ds,ax
mov bx,0
mov ax,b
mov ss,ax
mov sp,16 ;或sp,10H
mov cx,8
s: push [bx]
add bx,2 ;或两个 inc bx 指令
loop s
mov ax,4c00h
int 21h
)
code ends
end start
- 实验8 这个程序可以正确返回吗? 运行后为什么是这种结果? ■■■详解
- -----------7.9------------有两种方式改变大写字母
- 第六章---------实验6.1 (1) (2)---------详细解答,,,,,,,,~~ 准确答案亲自实验.....不懂提问----------------------------------
- 实验4 --------------____________________________________----个人解释
- ■■■■■■■■■■■■■■■■■实验 10.3 结合 ■除法溢出 ■指定输出字符\颜色 ■数值显示 附□倒序
- ■■■■■■■■■■■■■■■■实验 10.1 万用子程序 (指定位置输出字符与颜色)
- 高手看一下,用本章前的所有知识怎么搞黑客帝国的数字雨效果-.-
- ■■■实验8■■■■实验9 -----------------------过程,,, 源程序测试过■■★ ★
- 实验 9. 3 ■■■ 用loo指令查找内存2000H段中第一个值为0的字节,找到后存储在dx中 ■ ■■■■详细解答
- 实验 7 --------------------准确答案,, 自己编写..经调试验证~~~~~~~~~~~~~~~~~~~~~~~~~~~~~