2014年3月4日 星期二 23时11分30秒
第六章 包含多个段的程序
0:200~ 0:2FF 是相对安全的。但这段空间只有256个字节。
程序取得空间的两种方法:一是在加载程序的时候为程序分配,二是程序在执行过程中向系统申请
6.1 在代码中使用数据
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
dw 的含义是定义字型数据。
伪指令end的作用不仅可以通知编译器程序结束处,还可以通知编译器程序的入口在什么地方。即mov bx,0 是程序的第一条指令。
6.2 在代码段中使用栈
assume cs:code
code 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
start:
mov ax,cs
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
6.3 将数据,代码,栈放入不同的段
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 cx,8
mov bx,0 ;ds:bx指向data段中的第一个单元
s:push ds:[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
(1)定义多个段的方法
(2)对段地址的引用
地址分为段地址和偏移地址。在程序中,段名就相当于一个标号,它代表了段地址。所以指令"mov ax:data"的含义就是将
名称为"data"的段地址送入ax。偏移地址就要看它在段中的位置了。例如程序"data"段中的数据"0abch"的地址就是"data:6"。
要将它送入bx,则要用如下的代码:
mov ax,data
mov ds,ax
mov bx,ds:[6]
不能用如下的命令:
mov ds,data
mov bx,ds:[6]
因为8086CPU不允许将一个数值直接送入段寄存器中。
程序中对段名的引用,如指令"mov ds,data"中的"data"将被编译器处理为一个表示短地址的数值。
(3)"代码段","数据段","栈段"完全是我们的安排
实验5 编写,调试具有多个段的程序
assume cs:code, ds:data,ss:stack
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
data segment
dw 0123h,0456h
data ends
stack segment
dw 0,0
stack ends
end start
这样写,即使去掉start也能正确执行,因为程序默认的入口是程序的第一条指令。
--------------
;(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 8,7,6,5,4,3,2,1
c ends
code segment
start:mov cx,8
mov bx,0
mov ax,a
mov ds,ax
s:
mov al,ds:[bx]
add al,ds:[bx+16]
mov ds:[bx+32],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
----------------------
相加前的数据:
相加后的数据:
DW 定义一个字
DB 定义一个字节
DD 定义一个双字
前面的D表示定义,后面的字母W 、B 、D依次表示字(一般为16位)、字节(为8位)、双字(一般为32位),它们起的作用,一般是在程序中作变量使用。
(6)
;(6)程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中
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,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp,16
mov cx,8
mov bx,0
s:push ds:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
执行前的数据:
执行后的数据:
2014-4-7 20:45 记 @sanlihe.xichengqu.beijing
第六章 包含多个段的程序
0:200~ 0:2FF 是相对安全的。但这段空间只有256个字节。
程序取得空间的两种方法:一是在加载程序的时候为程序分配,二是程序在执行过程中向系统申请
6.1 在代码中使用数据
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
dw 的含义是定义字型数据。
伪指令end的作用不仅可以通知编译器程序结束处,还可以通知编译器程序的入口在什么地方。即mov bx,0 是程序的第一条指令。
6.2 在代码段中使用栈
assume cs:code
code 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
start:
mov ax,cs
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
6.3 将数据,代码,栈放入不同的段
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 cx,8
mov bx,0 ;ds:bx指向data段中的第一个单元
s:push ds:[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
(1)定义多个段的方法
(2)对段地址的引用
地址分为段地址和偏移地址。在程序中,段名就相当于一个标号,它代表了段地址。所以指令"mov ax:data"的含义就是将
名称为"data"的段地址送入ax。偏移地址就要看它在段中的位置了。例如程序"data"段中的数据"0abch"的地址就是"data:6"。
要将它送入bx,则要用如下的代码:
mov ax,data
mov ds,ax
mov bx,ds:[6]
不能用如下的命令:
mov ds,data
mov bx,ds:[6]
因为8086CPU不允许将一个数值直接送入段寄存器中。
程序中对段名的引用,如指令"mov ds,data"中的"data"将被编译器处理为一个表示短地址的数值。
(3)"代码段","数据段","栈段"完全是我们的安排
实验5 编写,调试具有多个段的程序
assume cs:code, ds:data,ss:stack
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
data segment
dw 0123h,0456h
data ends
stack segment
dw 0,0
stack ends
end start
这样写,即使去掉start也能正确执行,因为程序默认的入口是程序的第一条指令。
--------------
;(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 8,7,6,5,4,3,2,1
c ends
code segment
start:mov cx,8
mov bx,0
mov ax,a
mov ds,ax
s:
mov al,ds:[bx]
add al,ds:[bx+16]
mov ds:[bx+32],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
----------------------
相加前的数据:
相加后的数据:
DW 定义一个字
DB 定义一个字节
DD 定义一个双字
前面的D表示定义,后面的字母W 、B 、D依次表示字(一般为16位)、字节(为8位)、双字(一般为32位),它们起的作用,一般是在程序中作变量使用。
(6)
;(6)程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中
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,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp,16
mov cx,8
mov bx,0
s:push ds:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
执行前的数据:
执行后的数据:
2014-4-7 20:45 记 @sanlihe.xichengqu.beijing