文章目录
一、硬件基础知识
1.寄存器
寄存器是CPU内部的高速存储单元,访问速度比常规内存快很多。IA-32中较常使用的寄存器可以分为两类:一类是用于程序执行的基本寄存器,它包括8个通用寄存器,6个段寄存器,一个处理器状态标志寄存器(EFLAGS)和一个指令指针寄存器(EIP)
之前16位机的时候,数据寄存器为ax,bx,cd,dx,后面发展到32位机的时候,由于是扩展的(extern),所以名称前面加了个e。扩展的32位机是由两个16位的寄存器组合而成的,如果使用寄存器的高16位,则为ah/bh/ch/dh,如果使用寄存器的低16位,则为al/bl/cl/dl。
①EAX:累加器,使用频度最高
②EBX:基址寄存器,常用来存放存储器地址
③ECX:计数器,一般用于循环指令和重复前缀中,作为循环次数计数器
④EDX:数据寄存器,存放数据
⑤EFLAGS:标志寄存器,存在于CPU中,32位,包含一组状态标志,控制标志以及系统标志。
IF:中断允许标志,当IF=0时,会进入关中断模式。在汇编中 cli 语句会将 IF = 0,而开中断语句 sti 会将 IF = 1。
DF:方向标志位,当DF=1,存储器地址自动减少,从高位到低位处理指令;当 DF=0,存储器地址自动增加,从低位到高位处理指令,一般用于串操作中。(串操作是针对数据块或字符串的操作,实现存储器到存储器的数据传送)
⑥DS:数据段寄存器,一般存储全局变量的地址,有一个规定,立即数不能直接送入数据段寄存器,所以经常会有这样的代码:
mov ax,#INITSEG
mov ds,ax
⑦SI:源变址寄存器,一般 DS:SI 表示的地址即为 源地址
⑧ES:附加段寄存器,一般其他段寄存器不够用的时候用这个
⑨DI:目的变址寄存器,一般ES:DI 表示的即为 目的地址
⑩SS:堆栈段寄存器,保存堆栈的地址
⑪SP:堆栈指针,一般SS:SP 指向目前的堆栈位置
⑫CS:代码段寄存器,代码段区域的基地址
⑬IP:指令指针寄存器,一般CS:IP 表示的即为当前指令的起始地址
⑭FS与GS:段寄存器,没有处理器定义的目的,而是由操作系统运行它们来赋予目的。
而另一类则为系统寄存器,MS-Windows仅允许运行在最高特权级(特权级0)上的程序访问这些寄存器。
GDT(全局描述符表):系统中唯一的存放 段描述符 的数组,配合程序进行保护模式下的段寻址。可理解为所有进程的总目录表,其中存放每一个任务的局部描述符表(LDT)地址 和 任务状态段(TSS)地址,完成进程中各段的寻址、现场保护与现场恢复。由于GDT可以存储在内存的任意部分,因此在初始化GDT时需要先将GDT的基地址送入GDTR中以便后续方便查找GDT。全局表长2KB,一共256项,每项8B
IDT(中段描述符表):保存保护模式下所有中断服务程序的入口地址,类似于实模式下的中断向量表。其初始化也需要将 IDT 的基地址存入IDTR中才可以生效。
控制寄存器:共有4个,分别为CR0、CR1、CR2、CR3。这些寄存器仅能够由系统程序通过MOV指令访问。
2.程序在内存中的五个区域
3.磁道、扇区、磁头
4.实模式 / 保护模式
①实模式
以8086为例,保护模式下,8086段寄存器16位(段地址/基地址),寄存器16位(偏移地址),地址总线20位(寻址1M:2^20)
实际物理地址 = (段寄存器 << 4) + 偏移地址
访问到的是实地址,段内最大64K(2^16),但一个段可以小于64K。在编程时可以根据需要,将若干个地址连续的内存单元看做一个段,用段地址×16定位段的起始地址(基地址),用偏移地址定位段中的内存单元。如下图所示,我们可以认为:地址10000H~100FFH的内存单元组成一个段,该段的起始地址(基础地址)为10000H,段地址为1000H,大小为100H;我们也可以认为地址10000H~1007F、10080H~100FHH的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和10080H,段地址为:1000H和1008H,大小都为80H
注意:
1.在实模式下最大寻址空间时1M,1M以上的内存空间在实模式下不会被使用
2在实模式所有的内存数据都可以被访问,不存在用户态、内核态之分
3.在BIOS加载、MBR、ntdlr启动阶段都处在实模式下
②保护模式
引入保护模式的目的是,在执行多任务操作时,对不同任务使用的虚拟存储器空间进行完全的隔离,保护每个任务顺利执行。在保护模式下,分段机制是利用一个称作段选择符的偏移量到全局描述符表中找到需要的段描述符,而这个段描述符中就存放着真正的段的物理首地址,然后再加上偏移地址量便得到了最后的物理地址。在32位平台上,段物理首地址和偏移址都是 32 位的,实际物理地址的计算不再需要将段首地址左移 4 位了,直接相加即可,如果发生溢出的情况,则将溢出位舍弃
段选择符的结构:
段选择符长度为16位(2字节),位0至1表示请求的特权级0至3,其中内核为0特权,用户为3特权;位2用于选择全局描述符表(0)还是局部描述符表(1);位3-15是描述符表项的索引,指出选择第几项描述符。
二、汇编语言基本元素
1.符号常量
2.标识符
.global
.text .bss .data
3.伪指令
三、指令
1.跳转指令
①无条件跳转:JMP
②依据EFLAGS值决定跳转
③基于恒等性比较的跳转指令
基于 CMP 指令来判断两个操作数是否相等或CX,ECX是否为零的跳转指令。其中JNZ 与 JE 相反
cmp edx,0A523H
je L1
④段间跳转指令
jmpi go,INITSEG
jmpi为段间跳转指令,执行这条指令之后,CS = INITSEG,IP = go,也就是跳转到地址 INITSEG : go 。
2.中断指令
int
0x13需要的中断参数
3.标志操作指令
CLD:将标志寄存器FLAG的方向标志位DF清零
3.段超越
SEG命令
4.寻址方式
①立即数寻址
立即寻址方式的目的就是将操作数紧跟在操作码后面,其中Intel汇编使用 # 表示后面的变量是个立即数,直接将后面变量的值传入寄存器中,如果是AT&T汇编,则直接数以“$”开头。
mov ax,#INITSEG
立即数有的时候进制是不一样的,可以为2/8/16进制,通过在后面的标识符来判断哪个进制。二进制立即数后缀为B,十六进制后辍为H,十进制没有后缀
#00001111B //一个二进制的立即数
②间接寻址
Intel汇编间接寻址通常以一个 [ ] 表示,它会取括号中寄存器所存储的值作为指针,来找到对应单元的地址
mov al,[SI]
但也有可能方括号中直接是一个数值,这代表他给出的是一个偏移地址。当只给出偏移地址时,对于数据段隐含的段地址是DS。当给出SI时自然是和DS相对应,当给出DI时自然是和ES相对应。
mov [0],dx //相当于mov ds:[0],dx
5.运算指令
① CMP 目的操作数,源操作数
指令在源操作数和目的操作数之间执行隐含的减法操作,两个操作数都不会被修改。
② SUB 目的操作数,源操作数
目的操作数 = 目的操作数 - 源操作数,相相减的结果存储在目的操作数中。
③ ADD 目的操作数,源操作数
目的操作数 = 目的操作数 + 源操作数,相加的结果存储在目的操作数中。
④TEST 目的操作数,源操作数
Test命令将两个操作数进行逻辑与运算,并根据运算结果设置相关的标志位。但是,Test命令的两个操作数不会被改变。运算结果在设置过相关标记位后会被丢弃。
XOR
6.取地址指令
①LDS OPRD1,OPRD2
从存储器取出32位地址的指令,OPRD1 为任意一个16位的寄存器,OPRD2 为32位的存储器地址.
lds si,[4*0x41] //
7.移动指令
①MOVSB、MOVSW、MOVSD
指令从ESI指向的内存位置复制数据到EDI指向的内存为止,同时ESI和EDI寄存器自动增加或减少
一般三个mov语句前面都会跟着赋值CX(循环次数)和REP(开始复制)指令。
mov cx,#0x10 //复制0x10字节
rep
movsb
8.定义变量
①.word expression
在该位置上存放一个值为expression的变量
9. I/0指令
主要为 in指令 和 out指令
IN AL,21H;表示从21H端口读取一字节数据到AL
IN AX,21H;表示从端口地址21H读取1字节数据到AL,从端口地址22H读取1字节到AH
OUT 21H,AL;将AL的值写入21H端口
OUT 21H,AX;将AX的值写入端口地址21H开始的连续两个字节。(port[21H]=AL,port[22h]=AH)
10. 转移指令
一般通过 call指令 和 ret指令进行子程序调用,使用call指令时,会将下一条指令的IP压入栈中,等子程序调用结束后,在子程序中出现ret指令,就会将栈中的IP地址pop出来,以实现子程序的返回。
assume cs:code
code segment
start:
mov ax,1 ;1.ax=1
mov cx,3 ;2.cx=3
call s ;3.push 下一条指令的IP,jmp s处
mov bx,ax ;6.(bx)=8
mov ax,4c00h
int 21h
s:
add ax,ax
loop s ;4.ax=2^3次方,后结束这个loop
ret ;5.pop ip,就返回到6处
code ends
end start