段,位与指令指针寄存器

段,位与指令指针寄存器

RISC-V CSR寄存器(1)CSR简介和CSR指令

1.CSR简介

  相关参考文章:

RISC-V教学教案

  除去之前介绍的32个通用寄存器之外,还有一类扩展寄存器,称为CSR(control and status register,控制和状态寄存器)。

顾名思义,这类寄存器与控制CPU和表明CPU状态相关。

特权指令除了包括CSR指令外,还有其他的特权指令,这里将介绍6条操作CSR寄存器的CSR指令。

CSR寄存器中有些指定字段行为的定义和缩写,有以下几种[1]:

  1. WIRI:

Reserved Writes Ignored,Read Ignore Values(保留写入忽略,读取忽略值)

  1. WPRI:

Reserved Writes Preserve Values, Reads Ignore Values(保留写入保留值,读取忽略值)

  1. WLRL:

Write/Read Only Legal Values(读写合法值)

  1. WARL:

Write Any Values, Reads Legal Values(任意写,读合法值)

这里只做介绍,也不多做讨论。

所有的CSR指令都是每次只能对一个CSR寄存器操作,其机器码如图1所示。

可以看到CSR指令类似于I-type指令。

虽然也有12位的立即数域,但是实际上机器码的bit 20-31是用来 索引相应CSR寄存器的地址

所以理论上,一共可以实现2^12 = 4096位CSR寄存器。

按照惯例,CSR地址的高位(CSR[11:8]/机器码的bit 31-28)用于根据权限级别对CSR的读写可访问性进行编码。

前两位(CSR[11:10]/机器码的bit 31-30)指示该CSR寄存器是可读可写(00,01或10)还是只读(11)。

接下来两位(CSR[9:8]/机器码的bit 29-28)编码表明可以访问该CSR寄存器的最低特权级别 [1]。00 => user CSR;  01 => supervisor CSR; 10 => hypervisor CSR; 11 => machine CSR

CSR的opcode 是111_0011,被称为SYSTEM。

根据不同的funct3,可以确定不同的CSR指令。

 

 

 

 

 图1 CSR指令机器编码 [1]

这6条CSR指令又可以分为两类:

  • 一类是寄存器操作:

CSRRW,CSRRS,CSRRC

  • 一类是立即数操作:

CSRRWI,CSRRSI,CSRRCI。

对于立即数操作的3个指令,5位的立即数被放在了rs1的位置,被称为uimm[4:0],因为这些立即数是无符号(unsigned immediate)的。

这6条CSR指令的rd与一般指令的目的寄存器没有差别,位于机器码的bit 7-11,共5位的索引。

常用的CSR寄存器可以分为4组,分别为:

  • 用户模式(user mode)
  • 监控模式(supervisor mode)
  • 超级监控模式(hypervisor mode)
  • 机器模式(machine mode)。

机器模式是基础的,所有的RISC-V CPU必须实现的模式。

其他三种是可选的。

这里将只会介绍机器模式下的CSR寄存器。

2.CSR指令

2.1.CSRRW

CSRRW(control and status register read and write,读后立即写控制状态寄存器)指令格式为CSRRW rd,csr,rs1。

t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t 其机器码如图2所示,CSRRW的funct3是001。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,再把rs1寄存器中的值写入CSR寄存器。

举例说明:

CSRRW x13,mie,x12将mie寄存器里的值读出并赋值给x13寄存器,再把x12寄存器中的值写进mie寄存器 可以看到,其机器码如图2所示,CSRRW的

opcode为111_0011

funct3为001

mie寄存器索引地址为12’b0011_0000_0100

rs1为 5’b0_1100

rd为 5’b0_1101

所以CSRRW x13,mie,x12对应的机器码为0011_0000_0100_01100_001_01101_1110011,对应的16进制为32’h3046_16f3

 

 

 

 

 图 2 CSRRW机器编码格式 [2]

2.2.CSRRS

CSRRS(control and status register read and set,读后置位控制状态寄存器)指令格式为CSRRS rd,csr,rs1。

t = CSRs[csr]; CSRs[csr] = t | x[rs1]; x[rd] = t 其机器码如图3所示,CSRRS的funct3是010。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,且将CSR寄存器中的值和寄存器rs1中的值按位或(bitwise OR)的结果写入CSR寄存器。

指令示例:

CSRRS x13,mie,x12将mie寄存器里面的值读出并赋值给x13寄存器,并将mie寄存器里的值和x12寄存器里的值按位或的结果写入mie寄存器中。

 

 

 图3 CSRRS机器编码格式 [2]

2.3.CSRRC

CSRRC(control and status register read and clear,读后清除控制状态寄存器)指令格式为CSRRC rd,csr,rs1。

t = CSRs[csr]; CSRs[csr] = t &~x[rs1]; x[rd] = t 其机器码如图4所示,CSRRC的funct3是011。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,且将CSR寄存器中的值和寄存器rs1中的值取反后按位与(bitwise AND)的结果写入CSR寄存器。

指令示例:

CSRRC x13,mie,x12将mie寄存器里面的值读出并赋值给x13寄存器,并将mie寄存器里的值和x12寄存器里的值取反后按位与的结果写入mie寄存器中。

 

 

 图4 CSRRC机器编码格式 [2]

2.4.CSRRWI

CSRRWI(control and status register read and write immediate,立即数读后写控制状态寄存器)指令格式为CSRRWI rd,csr,zimm[4:0]。

x[rd] = CSRs[csr]; CSRs[csr] = zimm 这里的zimm[4:0]表示高位由0(zero)扩展的立即数。

其机器码如图5所示,CSRRWI的funct3是101。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,再把五位的零扩展的立即数zimm写入CSR寄存器。

指令示例:

CSRRWI x13,mie,5将mie寄存器里的值读出并赋值给x13寄存器,再把5'b0_0101高位扩展0成32'h0000_0005写进mie寄存器

 

 图5 CSRRWI机器编码格式 [2]

2.5.CSRRSI

CSRRSI(control and status register read and set immediate,立即数读后设置控制状态寄存器)指令格式为CSRRSI rd,csr,zimm[4:0]。

t = CSRs[csr]; CSRs[csr] = t | zimm; x[rd] = t 其机器码如图6所示,CSRRSI的funct3是110。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,且将CSR寄存器中的值和五位的零扩展的立即数zimm按位或(bitwise OR)的结果写入CSR寄存器(CSR寄存器的第五位及更高位不变)。

指令示例:

CSRRSI x13,mie,5将mie寄存器里的值读出并赋值给x13寄存器,再把5'b0_0101高位扩展0成32'h0000_0005和mie寄存器里的值按位或写进mie寄存器

 

 图 6 CSRRSI机器编码格式 [2]

2.6.CSRRCI

CSRRCI(control and status register read and clear immediate,立即数读后清除控制状态寄存器)指令格式为CSRRCI rd,csr,zimm[4:0]。

t = CSRs[csr]; CSRs[csr] = t &~zimm; x[rd] = t 其机器码如图7所示,CSRRCI的funct3是111。

该指令是把CSR寄存器中的值读出并赋值到rd寄存器中,且将CSR寄存器中的值和五位的零扩展的立即数zimm取反后按位与(bitwise AND)的结果写入CSR寄存器(CSR寄存器的第五位及更高位不变)。

指令示例:

CSRRCI x13,mie,5将mie寄存器里的值读出并赋值给x13寄存器,再把5'b0_0101高位扩展0成32'h0000_0005,取反后为32'hFFFF_FFFA和mie寄存器里的值按位与写进mie寄存器

 

 图7 CSRRCI机器编码格式 [2]

对于段寄存器/标志位寄存器/指令指针寄存器

对于这几个寄存器我们这里简单的介绍一下,在刚接触这几个寄存器的时候,并不用说非常深入的研究这几个寄存器,等积累到一定后,就很好理解了。

段寄存器

首先帖一下各个段寄存器和对应的含义

  • CS:Code Segement,代码段寄存器
  • SS:Stack Segment,栈段寄存器
  • DS:Data Segment,数据段寄存器
  • ES:Extra(Data) Segment,数据段寄存器
  • FS:Data Segment,数据段寄存器
  • GS:Data Segment,数据段寄存器

这里的用法就是不同的段代表了不同区域,最常见的就是数据段取值ds:[]和栈段取值ss:[],如图下OD中的汇编指令就是从数据段ds:[]中取值。这里重点在哪里呢?其实只要知道汇编指令中ds:[]这些是从那个段里取值就行,常见的如ss:[],ds:[]。这里的难点是fs寄存器,它用于SEH、PEB、TEB这些,不过这些都是之后的内容,大家这里知道就行。

从ds数据段中取值

 

 标志位寄存器

标志位寄存器算是比较难以理解的一个部分了,首先标志位寄存器是4字节大小的寄存器,而它的每个位都包含了不同含义

 

 逆向工程核心原理中标志位寄存器图

OD中列出了几个比较总要的标志位如下(逆向工程师偷师一下别人的资料):

  • CF:若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。这个标志指示无符号整型运算的溢出状态,这个标志同样在多倍精度运算(multiple-precision arithmetic)中使用。
  • PF:如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。
  • AF:如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。这个标志在BCD(binary-code decimal)算术运算中被使用。
  • ZF:若结果为0则将其置1,反之清零。
  • SF:该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)
  • TF:将该位设置为1以允许单步调试模式,清零则禁用该模式。
  • DF:这个方向标志(位于EFLAGS寄存器的第10位)控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。STD以及CLD指令分别用于设置以及清除DF标志。
  • OF:如果整型结果是较大的正数或较小的负数,并且无法匹配目的操作数时将该位置1,反之清零。这个标志为带符号整型运算指示溢出状态。

看了上面这些可能会有点懵,我们这里主要就说一下ZF、OF和CF这几个标志位,还是来一个实际例子来看看

#include<stdio.h>#include<Windows.h>
int main()
{
             int i = 1;
             if (i == 1)
             {
                          unsigned int a = 0xFFFFFFF5;           //无符号整型最大为0xFFFFFFFF,加0x25溢出
                          unsigned int b = 0x00000025;
                          unsigned int c = a + b;

                          int d = 0x7FFFFFF0;                         //有符号整型最大为0x7FFFFFFF,加0x25溢出
                          int e = 0x00000025;
                          int f = d + e;
             }

             return 0;
}

首先就是最简单的1=1的问题了,cmp指令就是“local.2-0x1”,这个汇编指令并不会改变local.2的值,那这里的运算用来做什么呢?其实就类似于if判断,然后这个判断用什么来标识结果呢?其实就是ZF标志位,ZF是当结果位0时置1,这里“local.2-0x1”运算结果为零,所以ZF置1,然后再结合下面的jnz就是完整的一个判断了。而jnz就是ZF=0时才实现跳转,至于jz/jnz这些跳转,我们这里可以暂时不用管,以后会列举出所有的跳转再慢慢对比。

判断设置ZF标志位

 

 然后就是CF和OF,CF是无符号整型溢出置1,OF是有符号整型溢出置1

 

 

 

 无符号溢出设置CF标志位

有符号溢出设置OF标志位

这里就简单的列举了3个例子,还有其他的大家可以自己写代码来测试一下

指令指针寄存器

所谓的指令指针寄存器就是我们用OD时最常见的eip,它指向的就是我们将要运行的汇编指令,而这里我们知道这个就行。下图就是我们运行完了0096DB63处的mov ebp,esp后,eip就指向了0096DB65

 

 寄存器窗口的eip和汇编代码窗口的eip

 

 

参考文献链接

Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021]. [2] D. Patterson and A. Waterman, The RISC-V reader. Berkeley: Strawberry Canyon LLC, 2018.

https://mp.weixin.qq.com/s/-JC9NhGeITuJRS1M33PMsw

blog.csdn.net/jn1158359

https://mp.weixin.qq.com/s/WTIWJQI1jEUE72Pt-W6tqQ

 

 

posted @ 2023-03-02 04:40  吴建明wujianming  阅读(685)  评论(0编辑  收藏  举报