不管什么样的操作系统什么样的计算架构,内存大致可以分为四个部分:
(1)代码区:这个区域存储着被装入执行的二进制机器代码,处理器会到这个区域取指并执行。
(2)数据区:用于存储全局变量等。
(3)堆区(heap):一般由程序员分配释放,进程可以在堆区动态地请求一定大小的内存,并在用完之后归还给堆区。动态分配和回收是堆区的特点。
(4)栈区(stack):由系统自动分配释放 ,用于动态地存储函数之间的关系,以保证被调用函数在返回时恢复到母函数中继续执行。
栈
假设这里有一个大箱子,有语文数学英语物理书,我要把这些书装进这个箱子里。应该怎么装
当然是一本一本的垒起来
并且 还要给最上面的一本书做个标记,这里以 红色五角星代替
并且如果我继续往里面放书,这个标记总会给最上面的一本书
请问如果我要拿走一本书,只能拿走哪本书?
肯定是物理书,因为它在最上面,并且我拿走它以后会把标记修改(标记总是给最上面的一本书)
了解了上面这个过程,我们再来理解栈
这个箱子就是栈,箱子->栈
最上面一本书的标记是栈顶标记,红色五角星->栈顶标记
把书往箱子里放这个过程叫做入栈,放书进箱子->入栈
从箱子最上面把物理书拿走的这个过程叫做出栈,把书拿出来->出栈
那么其实,你放的书是数据;存放的位置是内存地址;栈顶标记也是内存地址
在汇编里面 入栈是push指令,出栈是pop指令
入栈 PUSH将16位寄存器 或者 内存中的字型数据 -> 栈顶标记的上面
出栈 POP将栈顶标记所标识的字型数据 ->16位寄存器或者内存中
并且它们会不断的修改栈顶标记(总在最上面)
PUSH指令:
在栈中存储数据的命令,以16位为单位存储
一般格式:PUSH 源操作数
PUSH AX ;将AX的内容压入到栈里
PUSHF ;将标志寄存器的内容保存到栈中
入栈1.修改SP寄存器中的数值 sp=sp-2
2.将AX中字型数据存放到SS(段地址寄存器)和SP(偏移地址寄存器)所组合出来的内存地址中
POP指令:
将栈顶部的数据弹出至目的地的指令
一般格式:POP 源操作数
POP DX ; 将栈的顶部内容送到DX中
POPF ; 将栈的顶部内容作为标志寄存器弹出
出栈1.将SS(段地址寄存器)和SP(偏移地址寄存器)所组合出来的内存地址中的字型数据 存放到BX里
2.修改栈顶标记 SP=SP+2 成为新的栈顶标记
遵循 先进后出 (后进先出)
当AX=1122H、BX=3344H、CX=5566H时的堆栈中的行为
PUSH AX
PUSH BX
PUSH CX
POP CX
POP BX
POP AX
例:将AX和BX、WORD1和WORD2的内容相互替换
PUSH AX ; 把AX的内容推到栈中
PUSH BX ; 把BX的内容推到栈中
PUSH WORD1 ; 把WORD1的内容推到栈中
PUSH WORD2 ; 把WORD2的内容推到栈中
POP WORD1 ; 将顶部(WORD2)还原到WORD1
POP WORD2 ; 将顶部(WORD1)还原到WORD2
POP AX ; 将顶部(BX)还原到AX
POP BX ; 将顶部(AX)还原到BX
例2:使用堆栈编写程序,以相反的方式输出输入的字符
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
MOV AH,2
MOV DL,'?'
INT 21H ;输出回车
XOR CX,CX ;CX初始化0
MOV AH,1
INT 21H ;键盘输入
@WHILE:
CMP AL,0DH
JE @END_WHILE ;如果是回车就跳转END_WHILE
PUSH AX ;把AX的内容推到栈里
INC CX ;CX加1
INT 21H ;键盘输入
JMP @WHILE ;继续循环
@END_WHILE:
MOV AH,2
MOV DL,0DH
INT 21H
MOV DL,0AH
INT 21H ;输出回车换行
JCXZ @EXIT ;cx=0的时候跳转EXIT
MOV AH,2 ;输出
@TOP:
POP DX ;把栈顶部的还原到DX里
INT 21H ;输出
LOOP @TOP ;循环直到CX=0,每循环一次CX-1
@EXIT:
MOV AH,4CH
INT 21H
MAIN ENDP
END MAIN
字节序Endianness
往一个地址中写入一个数据,那么在内存中是如何存放这个数据的呢?
存储方法:大端字节序(Big-endian) 、小端字节序(Little-endian) 和 中端字节序(Middle-endian)
种类 | 0x1234的形式 | 0x12345678的形式 |
大端字节序 | 12 34 | 12 34 56 78 |
小端字节序 | 34 12 | 78 56 34 12 |
中端字节序 | - | 34 12 78 56 或 56 78 12 34 |
在这里0x1234:高位字节是0x12,低位字节是0x34
总结下来:
- 大端字节序:高位字节在前,低位字节在后
- 小端字节序:低位字节在前,高位字节在后