《汇编语言》总结03 —— 包含多个段的程序

在我们一开始写的汇编源程序时,只有一个代码段,现在有一个问题是,如果程序需要用其他空间来存放数据,使用哪里呢?在总结第二提到过0:200~0:2FF是相对安全的,可这段空间容量只有256个字节,如果我们需要的空间超过256个字节该怎么办?

在操作系统的环境中,合法地通过操作系统取得的空间都是安全的,因为操作系统不会让一个程序所用的空间和其他程序以及系统自己的空间相冲突。在操作系统允许的情况下,程序可以取得任意容量的空间。

程序取得所需空间的方法有两种,一是在加载程序的时候为程序分配,再就是程序在执行的过程中向系统申请。

我们在这只讨论第一种方法。

我们若要一个程序在被加载的时候取得所需的空间,则必须要在源程序中做出说明。我们通过在源程序中定义段来进行内存空间的获取。

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

(一)在代码段中使用数据

编程计算以下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

测试如下:

对上述汇编代码作如下说明:

  1. dw的含义是定义字型数据,dw即“define word”,在这里使用dw定义了8个字型数据,它们所占的内存空间的大小为16个字节。
  2. 这8个数据到底放在哪呢?程序在运行的时候CS中存放的是代码段的段地址,所以可以从CS中得到它们段地址,那它们的偏移地址是多少呢?因为用dw定义的数据处于代码段的最开始,所以偏移地址为0,这8个数据就在代码段的偏移0、2、4、6、8、A、C、E处。程序运行时,它们的地址就是CS:0、CS:2、CS:4、CS:6、CS:8、CS:A、CS:C、CS:E。
  3. 用bx存放加2递增的偏移地址,用循环来进行累加。在循环开始前,设置(bx)=0,cs:bx指向第一个数据所在的单元。每次循环中(bx)=(bx)+2,cs:bx指向下一个数据所在的单元。
  4. 通过上图,我们知道DS=0B3A,在前面我已经为大家提到过,在SA:0的前256个字节为PSP区,即SA+10H:0处开始存放代码,PSP区是DOS和程序进行通讯的,具体你可以去了解DOS工作原理。所以CS的值为CS=0B4A。
  5. 为什么没看到程序中的指令呢?实际上用u命令从0B4A:0000查看到的也是程序中的内容,只不过不是源程序中的汇编指令所对应的机器码,而是源程序中,我们可以用d命令更加清楚地查看一下程序中前16个字节的内容,如下:

    可以从0B4A:0010查看程序中要执行的机器指令,如下:

    是不是和我之前写的一样?

想一想,这样写是不是很完美?我个人认为这并不是我想要的结果。为什么呢?因为程序的入口处不是我们所希望执行的指令。那如何可以在系统中直接运行呢?我们可以在源程序中指明程序的入口所在,我将代码改动如下:

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

我在原来的基础上加了start这个标号,通知编译器程序的入口在什么地方。那编译是如何知道哪条指令是第一条执行的指令呢?答案在于end start这条,它指明了程序的入口点,被转化为一个入口地址,存储在可执行文件的描述信息中,当加载后,设置CS:IP,这样CPU就从我们希望的地址处开始执行。

(二)在代码段中使用栈

以下都是通过代码来说明

assume cs:codesg

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

s0:pop cs:[bx]

add bx,2

loop s0

mov ax,4c00h

int 21h

codesg ends

end start

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

对上面代码进一步优化

assume cs:code,ds:data,ss:stack

data segment

dw 0123h,0456h,0789h,0abch,0defh,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

mov ax,data

mov ds,ax

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

总结完毕!

时间: 2024-11-07 19:28:52

《汇编语言》总结03 —— 包含多个段的程序的相关文章

小甲鱼零基础汇编语言学习笔记第六章之包含多个段的程序

在前面的几个章节中,我们的程序都是只有一个代码段,本章我们开始学习如何编写包含多个段的程序. 1.在代码段中使用数据 首先考虑这样一个问题,计算以下8个数据的和,结果存放在ax寄存器中: 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H 在前面的课程中,我们都是累加某些内存单元中的数据,并不关心数据本身,可现在我们要累加就是已经给定了数值的数据. 代码如下: 1 assume cs:codesg 2 codesg segment 3 dw 0123H

汇编入门学习笔记 (五)—— 包含多个段的程序

疯狂的暑假学习之  汇编入门学习笔记 (五)-- 包含多个段的程序 参考: <汇编语言> 王爽 第6章 1.在代码中使用数据. assume cs:code code segment dw 0123h,0456h,0789h,0defh mov ax,0 mov bx,0 mov ax,4c00H int 21h code ends end dw 表示定义字型数据,db 表示定义字节型数据. 上面代码编译连接,用debug调试,-u cs:0 查看汇编代码,发现没有看到 mov ax,0  m

包含多个段的程序

在前一章我们提到0:200~0:2FF地址空间是相对安全的,但是这段空间的容量只有256个字节. 在操作系统中只要是通过操作系统申请的空间就都是安全的,操作系统负责给程序分配安全的空间.在操作系统允许的情况下,程序可以取得任意数量的空间. 按程序获取所需空间的时间,获取空间方法可分为两种: 在加载程序的时候为程序分配 在程序执行的过程中向系统申请 本书中不论描述第二种 对于汇编程序,如果需要他在被加载的时候取得所需的空间,就必须要在源程序中做出说明,对于汇编源程序来讲就是在汇编源程序中做出相应段

王爽《汇编语言》第三版 第六章 包含多个段的程序

6.1 在代码段中使用数据 "dw"的含义是定义字型数据.dw即define word. 由于它们在代码段中,程序在运行的时候CS中存放代码段的段地址,所以我们可以从CS中得到它们的段地址. 因为用dw定义的数据处于代码段的最开始,所以偏移地址为0,这8 个数据就在代码段的偏移0.2.4.6.8.A.C.E处. end 除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方. 6.2 在代码段中使用栈 6.3 将数据.代码.栈放入不同的段 我们用和定义代码段一样的方法来定义多个

汇编语言学习第六章-包含多个段的程序

本博文系列参考自<<汇编语言>>第三版,作者:王爽 在前面的介绍的程序中只有一个代码段.那么如果我们需要将代码,数据分别存储在不同的内存空间应该怎么办呢?我们知道我们不可能随便使用任何一段内存空间,因为我们这段内存地址空间可能存储着非常重要的内容.其实,这只是我们考虑的太多啦,一旦我们将程序载入内存后,操作系统为我们分配的用于程序运行的内存空间都是安全的,绝对不会与其他程序的内存空间相重叠的. 往往程序获取内存有两种方式:一种是在程序载入内存的时候操作系统已经分配好的内存空间,另外

汇编语言(王爽) 第6章包含多个段的程序

程序到了内存中我们分为code(代码)段,也就是大部分指令段,数据段,栈 6.1 在代码段中使用数据 上图 dw表示define word定义一个字,16位 会出现cs执行的前16位是数据段,后面才是指令,所以要把IP设成10h 或者直接在第一条指令前面在start,再在最后面的end start 程序运行的第一条不是汇编指令可能会报错把 6.2 在代码段中使用栈 这的题目都是从内存单元的数据换到另一个内存单元 开始奇怪,为啥不直接换,还要专门定义一个栈空间出来做个中间体 查了资料才知道,内存单

汇编语言学习笔记(6)——包含多个段的程序

1.程序取得所需空间的方法有两种,一种是在加载程序的时候为程序分配,再就是程序在执行的过程中向系统申请. 2.我们若要一个程序在被加载的时候取得所需的空间,则必须要在源程序中做出说明.我们通过在源程序中定义段来进行内存空间的获取 3.程序运行的时候,CS寄存器中存放代码段的段地址. 4.在源程序中使用end 标号来指明程序的入口(要执行的第一条指令),所以程序架构就可以如下: assume cs:code code segment -- 数据 -- start: -- 代码 -- code en

汇编语言——包含多个段的程序

多个段在一起 问题:利用栈,将程序中定义的数据段数据逆序存放. 1 assume cs:codesg ; 定义代码段的位置(codesg的值就是cs寄存器的值) 2 codesg segment 3 dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 4 ; dw(define word)的含义是定义字型数据,db->定义字节型数据 5 ; 由于我们是在代码段定义的这些数据,所以这些数据是在代码段的(即(cs)=(ds)) 6 dw 0,0,0,

汇编语言第六章-包含多个段的程序

(1)将下面的程序编译连接,用debug加载,跟踪然后回答问题 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 stack ends code segment start:  mov ax,stack   mov ss,ax mov sp,16 mov ax,data