本文已参与「新人创作礼」活动,一起开启掘金创作之路。
在代码段中使用数据
考虑这样一个问题,编程计算以下8个数据的和,结果存在 ax 寄存器中: 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H;
代码语言:javascript复制assume cs:codesg
codesg 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
codesg ends
end
1、dw 的含义【定义字型数据:define word,16字节】
- 在数据段中使用dw定义数据,则数据在数据段中;
- 在代码段中使用dw定义数据,则数据在代码段中;
- 堆栈段也是一样;
2、在程序的第一条指令前加一个标号 start
,并且这个标号在伪指令 end
后面出现,可以通知编译器程序在什么地方结束,并且也可以通知编译器程序的入口在哪里:
assume cs:codesg
codesg 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
codesg ends
end start
在代码段中使用栈
完成下面的程序,利用栈,将程序中定义的数据逆序存放。
代码语言:javascript复制assume cs:codesg
codesg segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
?
code ends
end
思路:
程序运行时,定义的数据存放在cs:0~cs:15单元中,共8个字单元。依次将这8个字单元中的数据入栈,然后再依次出栈到这 8 个字单元中,从而实现数据的逆序存放。
问题是,我们首先要有一段可当作栈的内存空间。我们可以在程序中通过定义数据来取得一段空间,然后将这段空间当作栈空间来用。
代码语言:javascript复制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
;用dw定义16个字型数据,在程序加载后,将取得16个字的
;内存空间,存放这16个数据。在后面的程序中将这段空间当作栈来使用
start: mov ax,cs
mov ss, ax
mov sp, 30h ;将设置栈顶ss:sp指向cs: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处
注意以下指令:
代码语言:javascript复制mov ax,cs
mov ss,ax
mov sp,32
要将 cs:16 ~ cs:31 的内存空间当作栈来用,初始状态下栈为空,所以 ss:sp 要指向栈底,则设置 ss:sp 指向 cs:32。
将数据、代码、栈放入不同的段
1、在前面我们在程序中用到了数据和栈,我们在编程的时候要注意何处是数据,何处是栈、何处是代码; 2、这样做显然有两个问题:
- 把他们放在一个段中是程序显得混乱;
- 前面程序中处理的数据很少,用到的栈空间也小,放在一个段里面没有问题,但数据、栈、代码需要的空间超过64KB,就不能放在一个段中(8086中一个段的容量不能大于64KB);
3、我们可以和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间; 4、将数据、代码、栈放入不同的段:
- 我们可以在源程序中为这三个段起具有含义的名称:
- 用来存放数据的段,我们将其命名为
data
; - 用来存放代码的段,我们将其命名为
code
; - 用来作栈空间的段,我们将其命名为
stack
; - 但是 CPU 看得懂吗?【不能】
- 我们在源程序中用伪指令:
assume cs:code,ds:data,ss:stack
,将 cs、ds 和 ss 分别和 code、data、stack 段相连,这样做了之后,CPU 是都就会将 cs 指向 code,ds 指向 data,ss 指向 stack,从而按照我们的意图来处理这些段呢? 【不能】,伪指令 CPU 看不懂,伪指令是给编译器看的; - 若要 CPU 按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令,才是 CPU 要执行的内容,需在在 code 段中给 DS,CS、SS 设置相应的值才能让 CPU 识别出数据段、代码段、堆栈段,其中汇编程序开始的地方(即代码段开始的地方)由 end 后面的标号所指向的地方给出;
5、assume 指令不可省略,至于为什么,需要以后多多体会;
检测题
(1)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,完成程序:
代码语言:javascript复制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]
________
add bx,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
(2)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:
代码语言:javascript复制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
start: mov ax, ____
mov ss,ax
mov sp, ____
mov ax,0
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
_________
add bx,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
答案:
(1)
mov cs:[bx],ax
(2)
cs
;- 24h或36;
pop cs:[bx]
或pop ss:[bx]
;