汇编(七):包含多个段的程序

在代码段中使用数据

考虑这样一个问题,编程计算以下8个数据的和,结果存在 ax 寄存器中:
0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H;

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

 

在代码段中使用栈

完成下面的程序,利用栈,将程序中定义的数据逆序存放。

assume cs:codesg
codesg segment
  dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

  ?

code ends
end

思路:

程序运行时,定义的数据存放在cs:0~cs:15单元中,共8个字单元。依次将这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
        ;用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处

注意以下指令:

mov ax,cs
mov ss,ax
mov sp,32

要将 cs:16 ~ cs:31 的内存空间当作栈来用,初始状态下栈为空,所以 ss:sp 要指向栈底,则设置 ss:sp 指向 cs:32。

将数据、代码、栈放入不同的段

1、在前面我们在程序中用到了数据和栈,我们在编程的时候要注意何处是数据,何处是栈、何处是代码;
2、这样做显然有两个问题:

  1. 把他们放在一个段中是程序显得混乱;
  2. 前面程序中处理的数据很少,用到的栈空间也小,放在一个段里面没有问题,但数据、栈、代码需要的空间超过64KB,就不能放在一个段中(8086中一个段的容量不能大于64KB);

3、我们可以和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间;
4、将数据、代码、栈放入不同的段:

  1. 我们可以在源程序中为这三个段起具有含义的名称:
  • 用来存放数据的段,我们将其命名为 data
  • 用来存放代码的段,我们将其命名为 code
  • 用来作栈空间的段,我们将其命名为 stack
  • 但是 CPU 看得懂吗?【不能】
  1. 我们在源程序中用伪指令:assume cs:code,ds:data,ss:stack,将 cs、ds 和 ss 分别和 code、data、stack 段相连,这样做了之后,CPU 是都就会将 cs 指向 code,ds 指向 data,ss 指向 stack,从而按照我们的意图来处理这些段呢?
    【不能】,伪指令 CPU 看不懂,伪指令是给编译器看的;

  2. 若要 CPU 按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令,才是 CPU 要执行的内容,需在在 code 段中给 DS,CS、SS 设置相应的值才能让 CPU 识别出数据段、代码段、堆栈段,其中汇编程序开始的地方(即代码段开始的地方)由 end 后面的标号所指向的地方给出;

5、assume 指令不可省略,至于为什么,需要以后多多体会;
 

检测题

(1)下面的程序实现依次用内存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]
        ________
        add bx,2
        loop s

        mov ax,4c00h
        int 21h
codesg ends
end start

 

(2)下面的程序实现依次用内存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

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]

Guess you like

Origin blog.csdn.net/weixin_46263782/article/details/120477936