原创 首页 技术

操作系统基础与开发中遇到的问题

LinJHS 2

前言

记录开发操作系统遇到的问题

寄存器

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

  • MOV

  • MOVSX——带符号扩展传送

    • 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 的值送入 EAX

    • MOV 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,SRC

  • NOT:逻辑非,对目的操作数按位取反,结果存入目的操作数。

    • 指令格式: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, OPRD

  • SAL:算术左移指令

  • SHL:逻辑左移指令

  • 指令格式:SAL(SHL) DEST,OPRD

  • 说明:

    • SAL、SHL指令功能完全相同,按照操作数OPRD的规定的移位位数对目的操作数进行左移操作,每移一位,最低位补 0,最高位移入标志位 CF 中

  • 算术左移和算术右移:主要用来进行有符号数的倍增、减半

  • 逻辑左移和逻辑右移:主要用来进行无符号数的倍增、减半

循环移位

  • ROL:循环左移

    • 将操作数首尾相接进行移位

  • ROR:循环右移

  • 指令格式:ROL(ROR) DEST,OPRD

串操作指令

  • 串指连续存放在存储器中的一些数据字节、字或双字。

  • 串操作允许程序对连续存放的数据块进行操作。

  • 串操作通常以 DS:ESI 来寻址源串,以 ES:EDI 来寻址目的串

指令名称

字节/字操作

字节操作

字操作

双字操作

字符串传送

MOVS 目的串, 源串

MOVSB

MOVSW

MOVSD

字符串比较

CMPS 目的串, 源串

CMPSB

CMPSW

CMPSD

字符串扫描

SCAS 目的串

SCASB

SCASW

SCASD

字符串装入

LODS 源串

LODSB

LODSW

LODSD

字符串存储

STOS 目的串

STOSB

STOSW

STOSD

  • 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 过程返回

条件转移指令

指令

转移条件

说明

JC DEST

CF = 1

有进位/借位时转移

JNC DEST

CF = 0

无进位/借位时转移

JE/JZ DEST

ZF = 1

相等/等于零时转移

JNE/JNZ DEST

ZF = 0

不相等/不等于零时转移

JS DEST

SF = 1

是负数时转移

JNS DEST

SF = 0

不是负数时转移

JO DEST

OF = 1

有溢出时转移

JNO DEST

OF = 0

无溢出时转移

JP/JPE DEST

PF = 1

有偶数个“1”时转移

JNP/JPO DEST

PF = 0

有奇数个“1”时转移

循环控制指令

  • 这类指令用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自加进行寻址的方式

  • 跳转寻址:当程序发生跳转时,下一条要执行的指令的具体地址由跳转指令给出

操作数寻址

  • 根据操作数的不同表示,其寻址方式不同

    • 立即寻址

    • 寄存器寻址

    • 直接寻址

    • 寄存器间接寻址

    • 寄存器相对寻址

    • 基址变址寻址

    • 相对基址变址寻址

    • 比例变址寻址

    • 基址比例变址寻址

    • 相对基址比例变址寻址

内存单元的寻址

有效地址的计算:

有效地址EA=基址+变址×比例因子+位移量有效地址\text{EA}=基址+变址\times 比例因子+位移量

默认的段寄存器

访存类型

段寄存器

缺省默认规则

指令

CS 代码段寄存器

用于取指令

堆栈

SS 栈段寄存器

堆栈操作,任何使用ESP或EBP作为基址寄存器的访存

局部数据

DS 数据段寄存器

除堆栈和目的串操作之外的其他数据的访问

目的串

ES 附加段寄存器

串处理指令的目的串

段超越前缀

可以自行选择段寄存器

  • 格式:段寄存器:指令操作数

  • 例: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]


参考资料:

  1. 《30天自制操作系统》

分享
如果这篇文章帮到你,可以请我喝一杯茶。

微信扫码打开

请我喝杯茶

如果这篇文章帮到你,可以请我喝一杯茶。

微信收款码
在商城请我一杯