栈
问题:执行call指令时,将IP保存到哪里去了(内存的哪里?),当ret返回时可以拿回来?
栈,是一段连续的内存单元,也就是一段连续的内存地址
栈顶标记是内存地址,段地址和偏移地址来表示。
在8086CPU中,在任意时刻将段地址寄存器SS和偏移地址寄存器SP所组合的内存地址当作栈顶标记。
push ax 修改SP寄存器中的数值 SP = SP - 2
将AX中字型数据 -> SS:SP所组合出来的内存地址中,即入栈
pop bx SS:SP所组合出来的内存地址中的字型数据 -> bx
修改栈顶标记 SP = SP + 2 ,成为新的栈顶标记,即出栈
依然是零碎笔记
-
我们在一段内存中存放数据——数据段存放了我们自己定义的数据
-
我们可以在一段内存中存放指令——指令段(代码段)存放了我们自己定义的指令
-
我们可以将一段内存定义成栈空间——栈段,因为我们处理数据的时候需要临时性的存放
-
我们如何让CPU按照我们的安排去访问这些内存段呢?
- 对于数据段来说, 段地址 -> ds段地址寄存器 [0],[1]… mov add sub 指令去访问这些内存单元;那么cpu 就会将我们定义的数据段中的内容,当作数据来访问
- 对于代码段来说。 我们可以 通过修改 CS IP 这2个寄存器 去指向 我们定义的 代码段;这样 CPU 就将 执行 我们定义的 代码段中的 指令
- 对于栈段来说,我们可以通过修改 SS:SP 这2个寄存器去决定栈顶标记在哪里;这样cpu 在执行 栈的操作时 比如 push pop 就会将 我们定义的 栈段 当作 栈空间使用 ,进行临时性的数据存放或者取出
-
不管我们如何安排,CPU 将内存中 某段内容 当作指令 是因为 CS:IP 指向那里;CPU将某段内存 当作 栈空间 是因为 SS:SP 指向那里
我们一定要清楚,我们是 如何安排 内存的。以及如何让 CPU 按照我们的 安排去 行事
数据从哪里来,指令从哪里来,临时性的数据 存放到哪里去…取决于我们对 CPU 中的 地址寄存器的 设置 CS IP SS SP DS 寄存器
编译和链接
编译masm:asm -> obj
链接link:;obj -> exe
inc:即increase,++的意思
指令
LOOP指令,循环指令,按照次数来跳转。循环次数、跳转次数保存在CX寄存器中。
两个步骤:
1、cx = cx -1
2、判断cx中的值,不为0则跳转(jmp)到标号(内存地址)位置继续执行;等于0则执行下面的指令。
小编程:将内存FFFF:0 ~ FFFF:F 内存单元中的数据复制到 0:200 ~ 0:20F中
; ds代表数据从哪里来;es寄存器代表,数据到哪里去
assume cs:code,ds:data,ss:stack
code segment
mov ax,0FFFFH
mov ds,ax
mov ax,20H
mov es,ax
mov bx,0
mov cx,16
copyNumber:
mov dl,ds:[bx]
mov es:[bx],dl
inc bx
loop copyNumber
mov ax,4C00H
int 21H
code ends
data segment
db 128 dup (0)
data ends
stack segment stack
db 128 dup (0)
stack ends
end
可优化的地方:dl是8位寄存器,是进行字节型数据的复制,我们可以利用dx寄存器进行字型数据的复制,可减少一半的循环赋值次数,代码如下:
; ds代表数据从哪里来;es寄存器代表,数据到哪里去
assume cs:code,ds:data,ss:stack
code segment
mov ax,0FFFFH
mov ds,ax
mov ax,20H
mov es,ax
mov bx,0
mov cx,8
copyNumber:
mov dx,ds:[bx]
mov es:[bx],dx
add bx,2
loop copyNumber
mov ax,4C00H
int 21H
code ends
data segment
db 128 dup (0)
data ends
stack segment stack
db 128 dup (0)
stack ends
end