第六章 包含多个段段程序
程序所需要空间有两种方法,一是加载程序时为程序分配,二是在运行时向系统申请(暂不讨论)
1)在一个段中存放数据,代码,栈,段情况
2)将数据,代码,栈放入不同段段中。
6.1 在代码段中使用数据
累加一下8个数据 存入ax中
0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
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]
add bx, 2
loop s
mov ax, 4c00h
int 21h
code ends
end
dw表示 define word 定义字型数据
由于前16个字节是自定义数据被debug翻译成汇编指令就会看不懂。
从cs:10h开始就是程序的内容
修改IP值为10h 用g t p之类的可以正常执行程序
但是直接中系统中执行会出问题。需要指明程序的入口
在入口处加入标号start
在end 后加上start 表面程序入口地址是start
assume cs:code
code segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
start mov bx, 0
mov ax, 0
mov cx, 8
s: add ax, cs:[bx]
add bx, 2
loop s
mov ax, 4c00h
int 21h
code ends
end start
修改后重新编译用debug查看入口的IP被设置为10h
这样代码可以正常运行。
可执行文件中有描述信息记录第一条指令的地址。程序被加载后加载器读取其描述信息获取入口地址,然后设置CS:IP
也就是用end 后加标号指明入口地址
一个基本的代码框架
assume cs:code
code segment
;data definition
start: ; code definition
mov ax, 4c00h
int 21h
code ends
end start
完成以下代码,利用栈,将程序中定义的数据逆序排放
assume cs:code
code segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h ;data definition
start: ;code definition
mov ax, 4c00h
int 21h
code ends
end start
可以用默认系统分配的栈(但是地址随机性加上系统不管理栈溢出问题)
编译后代码如下
assume cs:code
code segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h ;data definition
dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 16 x dword space for stack
start: mov ax, cs ;code definition
mov ss, ax
mov sp, 30h
mov bx, 0
mov cx, 8
s: push cs:[bx]
add bx, 2
loop s
mov bx, 0
mov cx, 8
s0: pop cs:[bx]
add bx, 2
loop s0
mov ax, 4c00h
int 21h
code ends
end start
运行结果如下
dw 可用于定义数据 或者 定义存储空间(静态区)
监测点
6.1 代码
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
add bx, 2
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
运行结果
2)用内存0:0~0:15单元中的内容修改程序中的数据,数据传送用栈来进行。
运行时0:0 ~f的数据会被修改运行之后重新check 0:0~f 与CS:0~f的数据
代码
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 dword space
start: mov ax, cs
mov ss, ax
mov sp, 24h
mov ax, 0
mov ds, ax
mov bx, 0
mov cx, 8
s: push [bx]
pop cs:[bx]
add bx, 2
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
运行结果
6.3 将数据,代码,栈放入不同的段。
将数据,空间,栈放一起有弊端
1)程序显得混乱
2)前面处理的数据少,如果超过64KB就不能放在一个段中(8086的限制 段容量不能大于64KB)
一个多分段的例子
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 ; 16 dword space of stacks
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 20h
mov ax, data
mov ds, ax
mov bx, 0
mov cx, 8
s: push [bx]
add bx, 2
loop s
mov bx, 0
mov cx, 8
s0: pop [bx]
add bx, 2
loop s0
mov ax, 4c00h
int 21h
code ends
end start
mov ds, data 是错误的。
因为8086不允许直接将数据送入段寄存器
mov ax, data会被编译器处理成一个表示段段段地址
1)cpu并不区分段,只是程序设计的安排
2)伪指令 assume cs:code, ds:data, ss:stack cpu并不会立拿cs 指向code ds指向data ss指向stack
3)需要用机器指令控制cpu
实验5 编写调试多个段的程序
5) 编写代码 将a段和b段段数据一次相加结果存入c段
assume cs:code
a segment
db 1, 2, 3, 4, 5, 6, 7, 8
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, c
mov ds, ax ; set data segment to c
mov bx, 0
mov cx, 8
s: mov ax, a
mov es, ax ; set es to a
mov dl, es:[bx]
mov ax, b
mov es, ax ; set es to b
add dl, es:[bx]
mov [bx], dl ; save the result to ds:[bx]
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end start
运行结果
6) 将a段中段前8个字数据逆序存储到b段段8个字单元中
assume cs:code
a segment
dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 0ah, 0bh, 0ch, 0dh, 0eh, 0fh, 0ffh
a ends
b segment
dw 0, 0, 0, 0, 0, 0, 0, 0
b ends
code segment
start: mov ax, b
mov ss, ax ; set ss to b
mov sp, 10h
mov ax, a
mov ds, ax ; set ds to a
mov bx, 0
mov cx, 8
s: mov ax, [bx] ; get data from (ds:bx)
push ax
add bx, 2
loop s
mov ax, 4c00h
int 21h
code ends
end start
运行结果如下