1.为什么需要分段,分段还涉及到了操作系统内存分段管理,这个可以参考操作系统内存管理方面的知识。
#为什么需要段寄存器
assume cs:code
code segment
dw 0123H,0456H,0789H,0abcH,0abcH,0abcH,0abcH // 这里在代码段存放了这些dw定义的数据
//所占空间为16个字节,但是程序执行时,这些不会是汇编指令对应的机器码,只是存放的数据
//这时候如果让程序执行起来会有问题,因为前面16位是数据,而不是指令
//所以这时候就应该自己手动吧cs:ip指导16位之后的位置。程序才能执行,这就是不分段的情况
//当然还可以加start
mov bx,0
mov ax,0
mov cx ,0
s: add ax,cs:[bx]
add bx,2
loop s
mov ax ,4cooH
int 21H
code ends
end
2.实现一个分段汇编程序
assume cs:code,ss:stack,ds:data
data segment //数据段寄存器
db 'welcome to masm!' //这里算字节,如果是ascii码表,一个单词占二个字节,如果是Unicode占三个字节
db 00000010B
db 00100100B
db 01110001B
data ends
stack segment //堆栈段定了以128个字节,全部是0
db 128 dup (0)
stack ends
code segment //代码段寄存器。指令
start: mov ax,stack //把堆栈里面的数据给了ax
mov ss,ax //把ax给了ss,直接数不能给堆栈段
mov sp,128 //把栈顶设置为了sp ss:sp 0000:0000 0000:0080H
mov ax,data //将数据给了ax
mov ds,ax //把ax 给了ds 将数据放入段寄存器中
jmp show_m //jmp实现了函数的调用 段内转移
xh: jmp xh
next: mov ax,4c00h
int 21h
show_m: //相当于一个函数名 offset 可以看到这个名字的偏移地址
mov bx,0b800h
mov es,bx
mov bx,16 ; ds:[bx] color
mov di,12*160+60 ; es:[di] zimu + color
mov cx,3
s_c: push cx
push di
mov si,0 ; ds:[si] zimu
mov cx,16
s_w: mov dl,ds:[si]
mov dh,ds:[bx]
mov es:[di],dx
inc si
add di,2
loop s_w
pop di
pop cx
inc bx
add di,160
loop s_c
jmp next
code ends
end start
为什么把数据从寄存器给段寄存器而不是直接操作寄存器??
1, 代码段寄存器CS:存放当前正在运行的程序代码所在段的段基值,表示当前使用的指令代码可以从该段寄存器指定的存储器段中取得,相应的偏移值则由IP提供。
2, 数据段寄存器DS:指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基值。
3, 堆栈段寄存器SS:指出当前堆栈的底部地址,即存放堆栈段的段基值。
4, 附加段寄存器ES:指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。
什么时候使用cs: ds ss: es??
cs只是代码段,不对数据操作
ds在需要定义数据的时候使用
es 是对数据中的字符串需要做复制操作,从一片内存复制到另外一片内存的时候定义
es:di 作为目的操作地址,我们需要先定义目的操作地址的位置,然后在定义ds:si源操作地址的位置,然后做串复制操作
不光光是数据指令可以进行操做,代码段指令也可以进行串操作,本质来讲,数据和代码指定都是二进制。