首页 > 代码库 > 小甲鱼零基础汇编语言学习笔记第六章之包含多个段的程序
小甲鱼零基础汇编语言学习笔记第六章之包含多个段的程序
在前面的几个章节中,我们的程序都是只有一个代码段,本章我们开始学习如何编写包含多个段的程序。
1、在代码段中使用数据
首先考虑这样一个问题,计算以下8个数据的和,结果存放在ax寄存器中:
0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
在前面的课程中,我们都是累加某些内存单元中的数据,并不关心数据本身,可现在我们要累加就是已经给定了数值的数据。
代码如下:
1 assume cs:codesg 2 codesg segment 3 dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 4 mov bx,0 5 mov ax,0 6 mov cx,8 7 s: add ax,cs:[bx] 8 add bx,2 9 loop s 10 mov ax,4c00h 11 int 21h 12 codesg ends 13 end
在该程序第一行中的"dw"的含义是定义字型数据,即define word。在这里,我们使用dw定义了8个字型数据(数据之间用逗号分隔),它们所占的内存空间大小为16个字节。
将代码进行编译,连接后,使用debug进行调试,我们可以看到,在地址0B4FH:0000这个地址单元中,存放了我们定义的字型数据:
在0B4FH:0010开始的地址单元中,存放了我们的指令:
但是我们查看0B4F:0000这个地址单元时,它却并没有存放我们的指令(按理说应该是会存放我们的指令的,但是我们的指令却是存放在0B4FH:0010开始的地址单元中):
出现这样的原因是,cpu读取的是指令所对应的机器码,从0B4F:0000开始的地质单元中,存放的是由数据0123h、0456h等我们预先定义好的字型数据转换成机器码所对应的指令,这样造成了cpu的误读。要解决这个问题,我们就应该给程序指定一个入口,而不是直接从定义字型数据的指令开始,所以程序应该改为如下所示:
1 assume cs:codesg 2 codesg segment 3 dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 4 start:mov bx,0 5 mov ax,0 6 mov cx,8 7 8 s: add ax,cs:[bx] 9 add bx,2 10 loop s 11 12 mov ax,4c00h 13 int 21h 14 codesg ends 15 end start
我们重新编译连接这个程序,然后使用debug调试后,使用r命令查看寄存器的情况,可以发现,cs:ip默认就指向了程序的第一条指令,这是因为我们在程序中定义了一个程序的入口,但是程序是根据最后的end来查找程序的入口的,这一点要特别提醒一下。debug调试如图所示:
2、在代码段中使用栈
首先我们还是考虑一个问题,利用栈将程序定义的数据逆序存放,这个程序的代码应该如何来写?
当我们看到逆序存放这样的字眼的时候,就应该首先想到栈,应为要实现逆序,就必定会用到栈“LIFO”这个特性(后进先出)。所以程序的代码如下所示:
1 assume cs:codesg 2 codesg segment 3 dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 4 dw 0,0,0,0,0,0,0,0 ;这里用dw定义8个字型数据,在程序加载后,将取得8个字的内存空间,存放这8个数据,我们在后面的程序中 ;就将这段空间当做栈来使用。 5 6 start:mov ax,cs 7 mov ss,ax 8 mov sp,32 ;这里设置栈顶ss:sp指向cs:32 9 mov bx,0 10 mov cx,8 11 s: push cs:[bx] 12 add bx,2 13 loop s ;这里是将代码段0~16单元中的8个字型数据依次入栈 14 15 mov bx,0 16 mov cx,8 17 s0: pop cs:[bx] 18 add bx,2 19 loop s0 ;这里依次出栈8个字型数据到代码段0~16单元中 20 21 mov ax,4c00h 22 int 21h 23 24 codesg ends 25 end start
在编译连接这段程序后,我们使用debug来查看程序的运行情况:
我们是用t和d命令,来看看执行指令后,内存单元中的存储情况:
此时使用d命令来查看内存的情况:
3、将数据、代码、栈放入不同的段中
在前面的程序中,我们将数据、代码、栈放在了同一个段中,这样使程序显得很混乱。假如程序中的数据、代码、栈不大的话,这样做没问题,但是程序变大后,程序将变得很难看。在8086CPU中,如果数据、代码、栈的空间需求大于了64kb的话,这三者就不能存放在同一个段中,需要分开来存放。那么应该如何定义多个段呢?
我们使用定义代码段一样的方法来定义多个段,在这些段里面定义需要的数据,或通过定义数据来取得栈空间。现在我们还是考虑同样的一个问题,将栈中的数据逆序存储到一个寄存器中,代码入下所示:
1 assume cs:code,ds:data,ss:stack 2 3 data segment 4 dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 5 data ends 6 7 stack segment 8 dw 0,0,0,0,0,0,0,0 9 stack ends 10 11 code segment 12 start:mov ax,stack 13 mov ss,ax 14 mov sp,16 ;设置ss指向stack,设置ss:sp指向stack:16,cpu执行完这些指令后,就将stack段当做一个栈空间来使用。 15 mov ax,data 16 mov ds,ax ;想要ds:bx访问数据段,ds就要指向ax 17 mov bx,0 18 mov cx,8 19 s: push [bx] 20 add bx,2 21 loop s 22 23 mov bx,0 24 mov cx,8 25 s0: pop [bx] 26 add bx,2 27 loop s0 28 code ends 29 end start
在上面的代码中,我们定义了数据段data,栈段stack,代码段code,分别用ds,ss,cs指向这些段。这样做,看上去整个程序非常清晰明了。
CPU如何处理我们定义的段中的内容,是当做指令来执行,当做数据访问,还是当做栈空间来使用,完全是靠程序中具体的汇编指令和汇编指令对CS:IP、SS:SP、DS等寄存器的设置来决定的。
小甲鱼零基础汇编语言学习笔记第六章之包含多个段的程序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。