操作系统基础与开发中遇到的问题
前言
记录开发操作系统遇到的问题
寄存器
16 位寄存器
AX——accumulator,累加寄存器
CX——counter,计数寄存器
DX——data,数据寄存器
BX——base,基址寄存器
SP——stack pointer,栈指针寄存器
BP——base pointer,基址指针寄存器
SI——source index,源变址寄存器
DI——destination index,目的变址寄存器
注意:对于
MOV AL, BYTE [BX]
只有 BX、BP、SI、DI 才能指定内存地址
其余 AX、CX、DX、SP 不能用来指定
8 位寄存器
AL——累加寄存器低位(accumulator low)
CL——计数寄存器低位(counter low)
DL——数据寄存器低位(data low)
BL——基址寄存器低位(base low)
AH——累加寄存器高位(accumulator high)
CH——计数寄存器高位(counter high)
DH——数据寄存器高位(data high)
BH——基址寄存器高位(base high)
段寄存器
在最开始,地址最高有 20 位,但是 CPU 是 16 位的。
$物理地址 = 段基址 \times 10h + 偏移量$
ES——附加段寄存器(extra segment)
CS——代码段寄存器(code segment)
SS——栈段寄存器(stack segment)
DS——数据段寄存器(data segment)
FS——标志段寄存器(segment part 2)
GS——全局段寄存器(segment part 3)
标志/控制/状态寄存器

方向标志(Direction Flag, DF)
DF=0,从低地址到高地址
DF=1,从高地址到低地址
状态标志
CF——进位标志位(Carry Flag)
无符号数运算中使用,包括进位和借位
OF——溢出标志位(Overflow Flag)
有符号数运算中使用
AF——辅助进位标志位(Auxiliary Carry Flag)
在字操作时,发生低字节向高字节进位或借位时
在字节操作时,发生低4位向高4位进位或借位时
PF——奇偶标志位(Parity Flag)
SF——符号标志位(Sign Flag)
ZF——零标志位(Zero Flag)
指令指针寄存器
EIP——指令指针寄存器(Extended Instruction Pointer)
在 16 位系统中:
保存着 CPU 下一条将要执行指令的偏移量(相对于 CS 代码段寄存器)
在 32 位系统中:
往往直接保存 CPU 下一条将要执行指令的地址
不能直接修改 EIP 的值,只能通过其他指令间接修改
x86 指令集
数据传送指令
MOV
MOVMOVSX——带符号扩展传送MOVSX EAX, BL:将80H扩展为FFFFFF80H后送EAX中
MOVZX——带零扩展传送MOVZX AX,BL:将80H扩展为0080H后送AX中
注意
两个存储单元之间不能直接进行数据传送;两个段寄存器之间不能直接进行传送信息
立即数、代码段寄存器CS 只能作源操作数
IP 寄存器两个操作数都不能做

PUSH POP 堆栈操作指令
PUSH:操作数进栈PUSHA:把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈。PUSHAD:把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈。POP同理(出栈到目的操作数,把当前的SP所指向的堆栈顶部的一个字送到指定的目的操作数)
数据交换指令
XCHG:交换两操作数。允许通用寄存器之间,通用寄存器和存储器之间交换数据。
地址传送指令
LEA(Load Effective Address):将源操作数的有效地址传送到通用寄存器例:
LEA EAX, [EBP + var_cc]:将EBP + var_cc的值送入 EAXMOV EAX, [EBP + var_cc]:将存储在地址EBP + var_cc上的变量值送入EAX
标志寄存器传送指令
PUSHF——16位标志寄存器进栈PUSHFD——32位标志寄存器进栈POPF——16位标志寄存器出栈POPFD——32位标志寄存器出栈
算术运算指令
加法指令
ADD:将源操作数和目的操作数相加,结果送到目的操作数。ADC:将源操作数与目的操作数以及CF值相加,结果传送到目的操作数。注:ADD,ADC 指令影响的标志位是 OF,SF,ZF,AF,PF,CF
INC:目的操作数加一,结果送入目的操作数目的操作数可以为通用寄存器或存储器操作数
减法指令
SUB:将目的操作数减去源操作数,结果送入目的操作数(前面的-后面的,放在前面的)。SBB:将目的操作数减去源操作数,再减去CF值,结果送入目的操作数。注:SUB,SBB指令影响的标志位是 OF,SF,ZF,AF,PF,CF
DEC:目的操作数减一,结果送入目的操作数目的操作数可以为通用寄存器或存储器操作数。
注:INC,DEC 指令影响的标志位为 OF,SF,ZF,AF,PF
乘法指令
MUL:无符号数乘法指令,将源操作数和累加器中的目的操作数相乘,结果送入累加器中IMUL:有符号数乘法指令,将源操作数和累加器中的目的操作数相乘,结果送入累加器中指令格式:
MUL(IMUL) SRC说明:MUL,IMUL 指令的源操作数为通用寄存器或存储器操作数,目的操作数缺省存放在 ACC 累加器(AL,AX,EAX)中。
除法指令
DIV:无符号除法指令IDIV:有符号除法指令指令格式:
DIV(IDIV) SRC说明:DIV、IDIV 指令的源操作数作为除数,为通用寄存器或存储器操作数,目的操作数作为被除数,目的操作数缺省存放在ACC累加器(AL,AX,EAX)中
EAX/SRC -> 除数 EAX、商 EDX
逻辑运算和移位指令
逻辑运算指令
AND:逻辑与,目的操作数和源操作数按位进行逻辑与运算,结果存目的操作数。OR:逻辑或,目的操作数和源操作数按位进行逻辑或运算,结果存目的操作数。源操作数可以是通用寄存器、存储器操作数或立即数,目的操作数是通用寄存器或存储器操作数。
XOR:逻辑异或,目的操作数和源操作数按位进行逻辑异或运算,结果存目的操作数。指令格式:
AND(OR/XOR/XOR) DEST,SRCNOT:逻辑非,对目的操作数按位取反,结果存入目的操作数。指令格式:
NOT DEST
TEST:目的操作数与源操作数按位进行逻辑与操作,并修改标志位,结果不回送目的操作数。指令格式:
TEST DEST, SRC注:TEST指令常用在检测某些条件是否满足,但又不希望改变原有操作数的情况下。紧跟在这条指令后面的往往是一条条件转移指令,根据测试结果产生分支,转向不同的处理程序
例
TEST ECX, ECX
JE Crackme.00401326 ; ECX=0 则跳
算术逻辑移位
SAR(Shift Arithmetic Right):算术右移按照操作数OPRD规定的移位位数,对目的操作数进行右移操作,每移一位,最低位移入标志位CF,最高位(符号位)保持不变。相当于对有符号数进行除2操作
SHR(Shift Logical Right):逻辑右移按照操作数OPRD规定的移位位数,对目的操作数进行右移操作,每移一位,最低位移入标志位CF,最高位补0
指令格式:
SAR(SHR) DEST, OPRDSAL:算术左移指令SHL:逻辑左移指令指令格式:
SAL(SHL) DEST,OPRD说明:
SAL、SHL指令功能完全相同,按照操作数OPRD的规定的移位位数对目的操作数进行左移操作,每移一位,最低位补 0,最高位移入标志位 CF 中
算术左移和算术右移:主要用来进行有符号数的倍增、减半
逻辑左移和逻辑右移:主要用来进行无符号数的倍增、减半
循环移位
ROL:循环左移将操作数首尾相接进行移位
ROR:循环右移指令格式:
ROL(ROR) DEST,OPRD
串操作指令
串指连续存放在存储器中的一些数据字节、字或双字。
串操作允许程序对连续存放的数据块进行操作。
串操作通常以
DS:ESI来寻址源串,以ES:EDI来寻址目的串
MOVS 目的串, 源串字符串传送指令,把由ESI作指针的源串的字节或字,传送到由EDI作指针的目的串中
CMPS 目的串, 源串字符串比较指令,由
DS:ESI规定的源串元素减去ES:EDI指出的目的串元素,结果不回送,仅影响标志位 CF,AF,PF,OF,ZF和SF
SCAS 目的串串扫描指令,比较
EAX中内容与目的串中内容进行比较,由EAX的内容减去ES:EDI规定的目的串元素,结果不回送,仅影响标志位CF,AF,PF,SF,OF,ZF
LODS 源串串装入指令,将
DS:ESI所指的源串元素装入累加器EAX中
STOS 目的串串存储指令,将累加器
EAX中值存入ES:EDI所指的目的串存储单元中
控制转移指令
无条件转移指令
JMP无条件转移CALL过程调用RET过程返回
条件转移指令
循环控制指令
这类指令用ECX计数器的内容控制循环次数,先将循环次数存放在ECX中,每循环一次ECX内容减1,直到ECX为0时循环结束
REP:当CX/ECX>0时重复REPE/REPZ:当ZF=1或比较结果相等,且CX/ECX>0时重复REPNE/REPNZ:当ZF=0或比较结果不相等,且CX/ECX>0时重复REPC:当CF=1且CX/ECX>0时重复REPNC:当CF=0且CX/ECX>0时重复
处理器控制指令
空操作指令
NOP(机器码0x90):空操作,除了使 EIP 增1外,不做任何操作
中断指令
INTn:软件中断指令,也称为软中断指令,其中n为终端类型号,其值必须在0~255的范围内可以在编程时安排在程序中的任何位置上,因此也被称为陷阱中断
浮点运算指令
如果一条汇编指令以字母 F 开头,则其大概率为浮点运算指令,CPU 中浮点运算单元主要负责处理此类指令
寻址方式
指令寻址:确定下一条要执行指令地址的方法
操作数寻址:确定当前指令操作数地址方法
指令寻址
顺序寻址:当程序不发生跳转时,通过EIP自加进行寻址的方式
跳转寻址:当程序发生跳转时,下一条要执行的指令的具体地址由跳转指令给出
操作数寻址
根据操作数的不同表示,其寻址方式不同
立即寻址
寄存器寻址
直接寻址
寄存器间接寻址
寄存器相对寻址
基址变址寻址
相对基址变址寻址
比例变址寻址
基址比例变址寻址
相对基址比例变址寻址
内存单元的寻址
有效地址的计算:
默认的段寄存器
段超越前缀
可以自行选择段寄存器
格式:
段寄存器:指令操作数例:
MOV EAX, ES:[EBP]
但有些情况下不允许修改:
串处理操作中目的串必须使用ES段,即默认为
ES:EDI不可修改压栈(push)、弹栈(pop)必须使用SS段,即默认为
SS:ESP不可修改指令必须存放在CS段中
基址变址寻址
操作数的有效地址由基址寄存器的内容与变址寄存器的内容之和获得
MOV EAX,[EBX][ESI],也可写成:MOV EAX,[EBX+ESI]通常将指令中的第二操作数的第一个寄存器作为基址寄存器,第二个寄存器作为变址寄存器
其中,ESP不能作为变址寄存器
基址比例变址寻址
例如:
MOV EAX, [EBX+ECX*4],也可写成MOV EAX, [EBX][ECX*4]
参考资料:
《30天自制操作系统》