8086汇编学习笔记08

包含多个段的程序

系列文章

在代码段中使用数据

程序在运行前,操作系统需要为程序分配内存空间。分配的内存空间是安全的,可以任意改写其中的值。

程序在读写内存前,应该先确保该内存是安全的。若程序需要一定空间,必须在源程序中作出声明。

可以在汇编代码中使用关键字 dw 伪指令定义一系列字型数据(define word),数据之间以逗号分隔,例如:

dw 0123h, 4567h, 89abh, 0cdefh

定义完成后,这一系列字型数据会和代码一起被加载到内存中

程序在运行时,可以通过寄存器 CSIP 得到以上数据的段地址和偏移地址。它们在内存中与机器指令的相对位置和在源程序中与汇编指令的相对位置相同。

可执行文件( .exe 文件)的执行过程为:

  1. 由其它的程序将可执行文件中的程序加载入内存中
  2. 设置 CS:IP 指向程序中的第一条要执行的指令(即程序的入口),从而使程序开始执行
  3. 程序运行结束后,返回到加载它的程序

可以将这一系列字型数据与代码等价。为了区分数据和代码,通常将这一系列数据放到代码段的最前面,并跳过它们从有意义的代码开始执行

有两种方法可以做到这一点:

assume cs: codesg
codesg segment
    ; ...data...
start:
    ; ...code...
codesg ends
end start

程序中在第一条指令前出现了一个标号 start ,这个标号在伪指令 end 后面也出现了。

end 除了告知编译器程序结束之外,还可以指明程序的入口在标号“ start ”处。

assume cs: codesg
codesg segment
    JMP begin
    ; ...data...
begin:
    ; ...code...
codesg ends
end

由于标号本质上是标记代码所处的偏移地址,因此可以使用 JMP 指令直接修改寄存器 IP 为标号所处的偏移地址。

程序中的数据、代码与栈

可以在程序的代码段中通过定义一些无用的数据,来取得一部分空间,然后将这一段空间当做栈空间来使用

一个段最大的容量只有64KB,将数据放入代码段中,会挤占代码的空间。更好的方法是将数据、代码和栈放入不同的段中。

定义多个段的方法是定义代码段方式的扩展,只是对于不同的段,要使用不同的段名

assume cs: codes, ds: datas, ss: stacks
datas segment
    ; ...data...
datas ends
stacks segment
    ; ...stack...
stacks ends
codes segment
start:
    ; ...code...
codes ends
end start

程序分为了多个段,段名就相当一个标号,标号代表了段地址

例如,指令“ MOV AX, data ”就是将名称为“ data ”的段的段地址送入 AX 寄存器中。

可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元。

可以用一个段存放数据,段地址存放在 DS 段寄存器中,用 MOVADD 等指令访问内存单元,将其定义为数据段
可以用一个段当做栈使用,段地址存放在 SS 段寄存器中,将栈顶单元的偏移地址放在 SP 寄存器中,用 PUSHPOP 等指令操作栈,将其定义为栈段
可以用一个段存放代码,段地址存放在 CS 段寄存器中,将段中的第一条指令存放在 IP 寄存器中,CPU执行该段的指令,将其定义为代码段

这些段完全是人为定义的,段的大小取决去程序安排的大小,段的位置取决于代码的位置,段的访问取决于相应寄存器的设置

以下示例程序利用数据段保持一段数据,利用栈段和代码段将保存的数据逆序存放:

assume cs: codes, ds: datas, ss: stacks
datas segment
    dw 1122h, 3344h, 5566h, 7788h, 99aah, 0bbcch
datas ends
stacks segment
    dw 0, 0, 0, 0, 0, 0, 0 ,0
stacks ends
codes segment
start:
    mov ax, stacks
    mov ss, ax
    mov sp, 0fh   ; set SS:SP to stacks:0fh
    mov ax, datas
    mov ds, ax      
    mov bx, 0     ; set DS:[BX] to first unit of stack segment
    mov cx, 6
copy:
    push [bx]
    add bx, 2
    loop copy     ; push 6 words into stack
    mov bx, 0
    mov cx, 6
reverse:
    pop [bx]
    add bx, 2
    loop reverse  ; pop 6 words in stack to data segment
    mov ax, 4c00h
    int 21h
codes ends
end start