段的概念
8086cpu中机器字长是16位,一个寄存器能储存的位数是16位,但是和8086匹配的内存是20位,怎么通过16位寻找20的地址呢?采用段地址+偏移地址的方法,20位物理地址 = 16位段地址 * 16(10h) + 16位的偏移地址,以16进制数来看,比如地址为20001h的物理地址,我们可以把物理地址写成 2000h * 16(10h) + 0001h 2000h就是段地址,0001h就是偏移地址。
段的大小:一个段最大为64K * 1B,就是64KB,比如以2000h为段地址的段,其范围为 20000h ~ 2ffffh 即64K,而内存的存储字长是1B,所以为64KB
段的作用:段扩展了cpu的寻址能力,从之前的16位到20位,当然实现段是要付出一些代价。 段也有保护的作用,可以看到如果段2000h,我们只能访问到20000h ~ 2ffffh,其余的地址我们是访问不到的。
段的实现:cpu怎么实现段的呢?在cpu中实现段寄存器,其中存放段地址,在实现地址部件,当需要寻址时,将段寄存器中的段地址 * 16 和 偏移地址相加,偏移地址我由我们直接给出,也可以由寄存器直接给出。
在debug程序访问内存
在debug程序中可以查看和更改内存中的值
-d 可以直接查看内存的二进制数 后面加地址查询指定地址的内存,不加地址会接着之前地址向下查询。
-u 可以查看内存中的汇编指令 换句话说可以把二进制数翻译成汇编指令在内存中,之后加加地址查询指定地址的内存,不加地址会接着之前地址向下查询。
-a 修改内存单元中的值 输入地址后会进入待输入数据状态,输入后会向下继续输出,输入完毕直接enter即可退出
注意:debug中输入物理地址全以 “段地址:偏移地址” 的形式,比如2000:0001
访问内存
[ ] 访问内存,[ ]中加上偏移地址,段地址由一般由ds段寄存器提供,比如我想访问 2000:0001的内存单元,可以如下指令访问
mov ax,2000
mov ds,ax
add [1],0
也可以指定段寄存器,例如add cs:[1],1
段
代码段
存放代码的段叫做代码段,我们知道运行程序时需要将代码的地址加载到 PC(program counter)然后cpu通过地址来寻找指令,8086的PC包含CS(code segment)寄存器和 IP(instruction pointer)寄存器,其中CS存放段地址,IP存放偏移地址
程序中一般是不会直接用mov指令来修改段寄存器的值,不允许直接用mov cs:立即数的形式,可以使用 mov cs:ax通过寄存器向其中传送指令,实际上修改cs或者ip中的值,就是转移指令,我们会用专门的指令去修改它,后面会详细介绍。
数据段
存放数据的段叫做数据段,ds(data segment)寄存器中存放着数据段地址,我们在指令中访问的内存单元不写段时一般默认为ds段
栈段
栈是程序中不可获取的一部分,它是一个数据结构,具有先进后出,后进先出的特点,可以储存函数参数,临时变量等一系列值。ss(stack segment)寄存器存放着段地址和sp(stack pointer)存放着栈偏移地址
访问栈,通过两条指令,pop push指令
pop pop+地址,将栈中数据弹到指定地址出,等于两条指令 mov [],ss:[sp], add sp,2 pop和push指令是以两个字节为单位,
在8086中, 一个字为两个字节
push push+地址,将指定地址压到栈中,等于两条指令 mov ss:[sp],[], sub sp,2
注意不能直接修改段寄存器的值,可以通过寄存器来修改段寄存器的值
三条汇编指令
add 加法指令 mov传送指令 sub减法指令
它们都是以 操作名 对象1,对象2的形式
对象1为目标对象,对象2为源对象