最全ARM体系结构知识:汇编、架构、异常级别和安全状态

发表于 3年以前  | 总阅读数:353 次

01

ARM汇编指令

操作系统中硬件相关的部分集中体现在汇编指令和对寄存器的操作中,因此我们对ARM体系结构的介绍也围绕ARMv8-A的汇编指令和寄存器来展开。

处理器架构是处理器厂商为同一个系列的处理器规定的一个规范。ARM架构是一种精简指令集(RISC)架构,具有以下RISC架构特点:

  • 较大的通用寄存器堆。

  • load/store体系结构,其中数据处理操作仅对寄存器内容进行操作,而不是直接对内存内容。

  • 简单寻址模式,所有load/store地址由寄存器内容和指令确定。该体系结构定义了处理单元与内存(包括缓存)的交互,并包括内存地址翻译系统。它还描述了多个处理单元如何相互作用。面积小、性能强和非常低的功耗是ARM体系结构的关键特性。本小节主要以ARMv8-A架构为例来介绍ARM体系结构的基本特性。ARMv8-A体系结构的一个重要特性是向后兼容,可以支持诸多标准和应用场景下的最优设计。ARMv8-A架构支持64bit的执行模式(AArch64)和32bit的执行模式(AArch32),这一模式兼容之前的ARM架构。两种执行状态都支持SIMD和浮点指令。

一、AMRv8架构概要

ARM体系结构自推出以来已经有了显著的发展,并且ARM还在继续开发它。到目前为止,已经有八个主要版本,由版本号1到8表示。其中前三个版本现在已经过时了。

通用名称AArch64和AArch32描述了64位和32位执行状态。AArch64是64位执行状态,意味着地址保存在64位寄存器中,并且基本指令集可以使用64位寄存器进行处理。AArch64支持A64指令集。AArch32是32位执行状态,这意味着地址保存在32位寄存器中,并且基本指令集使用32位寄存器进行处理。AArch32支持T32和A32指令集。

ARM支持三种架构配置:

  • A系列,面向应用场景的架构(Application Profile)。该系列支持基于内存管理单元(MMU)的虚拟内存系统体系结构(VMSA)。它支持A64、A32和T32指令集。

  • R系列,面向实时场景的架构配置。该系列支持基于内存保护单元(MPU)的受保护内存系统体系结构(PMSA)。它支持A32和T32指令集。

  • M系列,面向微处理器的架构。该系列实现了一个为低延迟中断处理而设计的程序员模型(programmers’ model),该模型具有寄存器硬件堆栈和对中断处理程序的高级语言支持。它支持T32指令集的变种。

    (注:内存保护单元(MPU)是ARM中配备的有效保护系统资源的一种硬件,提供了内存区域保护功能。)

二、ARMv8-A指令集

在ARMv8-A中,可能的指令集取决于执行状态:

1 . AArch64:AArch64 state只支持A64指令集。这是一个固定长度的指令集,使用32位指令编码。

2 . Arch32:AArch32 state支持以下指令集:

  • A32:这是一个固定长度的指令集,使用32位指令编码。它是与ARMv7 ARM指令集兼容。

  • T32:这是一个可变长度指令集,它同时使用16位和32位指令编码。它与ARMv7 Thumb®指令集兼容。

ARM指令的基本格式如下[2]:

<Opcode>{<Cond>}<S><Rd>,<Rn> {,<Opcode2>}

其中各个部分的含义为:

  • Opcode:操作码,也就是助记符,说明指令需要执行的操作类型;
  • Cond:指令执行条件码;
  • S:条件码设置项,决定本次指令执行是否影响PSTATE寄存器相应状态位值;
  • Rd/Xt:目标寄存器,A32指令可以选择R0-R14,T32指令大部分只能选择RO-R7,A64指令可以选择X0-X30;
  • Rn/Xn:第一个操作数的寄存器,和Rd一样,不同指令有不同要求;
  • Opcode2:第二个操作数,可以是立即数,寄存器Rm和寄存器移位方式(Rm,#shit);

ARMv8-A指令集的条件码如下图所示:

下面以A64指令集为例简要介绍ARMv8-A的指令体系。A64指令集中的指令主要分为控制指令、访存指令和计算指令。控制指令主要包括有条件分支指令、无条件分支指令、异常产生和返回指令、系统寄存器指令、系统指令、提示指令、同步指令和清除独占访问标志指令。访存指令主要有Load指令和Store指令,这两种指令有许多变种。计算指令包含算数指令、逻辑指令、MOVE指令、移位指令、位扩展指令和SIMD指令等等。以下列出了一些常用的控制指令的名称与用途。

1. 控制指令:

  • 条件分支指令:

  • 无条件分支指令:

  • 使用寄存器的无条件分支指令:

  • 异常产生指令:

  • 异常返回指令:

  • 系统寄存器指令:

  • 同步指令和独占状态清除指令:

例如:

2. 访存指令:

ARMv8访存指令支持以下寻址模式:

  • 基址加上无符号立即数的寻址和基址加上有符号立即数的寻址;
  • 基址加上寄存器偏移值;
  • 基址加上扩展的寄存器偏移;
  • pre-index模式;
  • post-index模式;
  • PC相对寻址模式。

具体情形见下表:

其中对于A64指令集来说,64bit的基址来自通用寄存器X0-X30或来自栈指针SP,立即数或寄存器偏移值则是可选的,对寻址方式的解释如下:

  • 寄存器偏移寻址是指来自64bit基址寄存器的地址加上一个偏移值;
  • Pre-indexed模式是指寻址地址是64bit基址加上一个偏移值,这个计算和将会写入基址寄存器;
  • Post-indexed模式是指寻址地址是64bit的基址,但之后基址和偏移值的和将会写入基址寄存器;由此可见pre-indexed和post-indexed的区别在于使用的地址是先加上偏移值再使用还是先使用再加上偏移值;
  • PC相对寻址是指寻址地址是这条指令64bit的PC值加上一个19bit的有符号字偏移,这个地址在当前指令的PC值的 ±1MB范围内并且是4byte对齐的。使用PC相对寻址所load的数据大小至少为32bit并且只能用来预取指令,且PC值不能被其他寻址方式使用。
  • 一个立即数偏移可以为有符号的,也可以为无符号的,可以为scaled也可以为unscaled。当一个立即数偏移是scaled的时候,它被编码为传输数据大小的整数倍。虽然汇编程序总是使用byte对齐的偏移,但汇编器或反汇编器会做必要的转换工作,因此可用的byte偏移值取决于load/store指令类型和数据传输的大小。

下面列出了一些load/store指令:

例如Load寄存器指令:

上表中指令的寻址方式有:

  • 基址加上12bit无符号scaled立即数偏移寻址;
  • 基址加上9bit有符号unscaled立即数偏移寻址;
  • 基址加上64bit寄存器偏移,可选为scaled;
  • 基址加上32bit可拓展寄存器偏移,可选为scaled;
  • 有unscaled9bit有符号立即数偏移的pre-indexed模式;
  • 有unscaled9bit有符号立即数偏移的post-indexed模式;
  • Load至少32bit数据的PC相对寻址模式。

如果被load或store的指令的寻址模式会修改基址寄存器的内容,且被load/store寄存器恰好的是基址所在的寄存器,那么硬件的行为可能不确定。

3.计算指令:

在操作系统汇编语言中使用的计算指令主要是一些简单的算数计算指令,用于对寄存器的move操作和对地址的计算操作,一般计算指令既可以使用立即数作为操作数,也可以使用寄存器中的数作为操作数。下面简单列举了一些算数指令:

使用立即数的简单算数指令:

例如:

使用寄存器的逻辑操作指令:

例如:

其中:

寄存器移位指令:

例如:

02

ARM架构寄存器

在处理器中,寄存器用于保存需要被快速访问的数据,在操作系统中需要特别注意的寄存器主要有栈指针寄存器(SP)、连接寄存器(LR)、程序计数器(PC)以及当前程序状态寄存器(CPSR)和保存程序状态寄存器(SPSR)。本小节主要以ARMv8-A为例介绍ARM架构的寄存器的基本情况。详情可参见文献[3],D1.6小节。

在这一小节中,我们主要介绍ARMv8架构中AArch64执行状态下的寄存器使用情况。ARM架构中的寄存器主要有两类,一类用于提供系统控制与状态报告;另一类用于指令运行和异常处理。我们主要讨论第二类。

通用寄存器主要用于基本指令集中的指令运行,通用寄存器共有31个,编号为R0-R31。这些通用寄存器可以被当成31个64bit的寄存器,编号为X0-X30;或者被作为31个32bit的寄存器,编号为W0-W30。

在AArch64执行状态下,除了通用寄存器外,每一个异常级别都会有一个栈指针寄存器(StackPointer Register, SP),栈指针寄存器为SPEL0和SPEL1。异常级别用于区分指令的执行权限,我们将在本章的第四期介绍。如果处理器实现中包含EL2,那么还有SPEL2。如果处理器实现中包含EL3,那么还有SPEL3。详情可参考链接[5]。

SIMD和浮点寄存器共用一系列寄存器,这些寄存器会用于浮点操作、向量操作和其它SIMD有关的标量操作。SIMD指令是能够复制多个操作数、并把它们打包在大型寄存器的一组指令集[3]。以加法指令为例,单指令单数据(SISD)的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数;之后再一次访问内存,取得第二个操作数;随后才能进行求和运算。而在SIMD型的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。浮点寄存器和SIMD寄存器共包含32个128bit位宽的寄存器,V0-V31。这些寄存器可以作为:

  • 32个双字(64bit)寄存器,D0-D31。
  • 32个单字(32bit)寄存器,S0-S31。
  • 32个半字(16bit)寄存器,H0-H31。
  • 32个单字(8bit)寄存器,B0-B31。

程序状态寄存器(Current Program Status Register,CPSR) 在用户级编程时用于存储条件码。CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。

保存程序状态寄存器(SPSR,Saved Program StatusRegister)用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。在A64中,不再使用单一的CPSR寄存器,来保存当前处理器状态,而是用PSTATE来保存处理器状态,而在A32中依然使用CPSR。有关PSTATE和CPSR的详细信息可参考链接[4]。A64中SPSR 格式的示意图如下图所示:

其中N、Z、C、V均为条件码标志位。它们的内容可被算术或逻辑运算的结果所改变,并且可以用于决定某条指令是否被执行,其含义如下表所示[8]:

标志位 含义
N 当两个有符号整数运算时:N=1表示运算的结果为负数;N=0表示运算的结果为正数或零。
Z Z=1表示运算的结果为零,Z=0表示运算的结果非零。
C 可以有4种方法设置C的值:在加法指令中(包括比较指令CMP),当结果产生了进位,则C=1,表示无符号运算发生上溢出;其他情况C=0。在减法指令中(包括减法指令CMP),当运算中发生借位,则C=0,表示无符号运算数发生下溢出;其他情况下C=1。对于包含移位操作的非加减运算指令,C中包含最后一次溢出的位的数值。对于其他非加减运算指令,C位的值通常不受影响。
V 对于加减运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号为溢出,通常其他指令不影响V位。

M[3:0]则用来确定异常级别和SP:

有关SPSR中各个位的详细信息可以参考文献[1] 1.6.4小节。

连接寄存器LR(R14)的主要作用有两个:

1. 保存子程序返回地址,用MOVE指令或BX指令可以用于实现返回,如MOV PC、LR或BXLR。若子程序中还需要调用子程序,则可以写为:

第一条指令将LR中的内容入栈,最后一条将栈中保存的LR寄存器的内容存入PC中用于返回。

2. 当异常发生时,异常模式的LR用于保存异常返回地址,将LR内容入栈可以处理嵌套中断。

PC是程序计数器,其中保存的是正在被加载的指令,而不是正在被执行的指令。例如,若指令长度为4byte,则PC指向当前正在被执行的指令的地址+8byte的地址。关于LR和PC的详细内容可参考文献[6]和[7]。

以下是异常级别EL3中使用的寄存器的例图:

ARM架构中处理器有不同的运行模式,因此同一个功能的寄存器在不同的运行模式下可能对应不同的物理寄存器,这些寄存器被称为备份寄存器。如SPSR_svc表示svc模式下使用的SPSR寄存器。ARM架构中常用的运行模式如下表所示[9]:

处理器模式 描述
用户模式(User, usr) 正常程序执行的模式
快速中断模式(FIQ, fiq) 用于高速数据传输和通道处理
外部中断模式(IRQ, irq) 用于通常的中断处理
特权模式(Supervisor, svc) 供操作系统使用的一种保护模式
数据访问中止模式(Abort, abt) 当数据或指令预取中止时进入该模式,用于虚拟存储及存储保护
未定义指令中止模式(Undefined, und) 当执行未定义指令时进入该模式,用于支持通过软件仿真硬件的协处理器
系统模式(System, sys) 用于运行特权级的操作系统任务

ARMv8-A架构还有Monitor(mon)工作模式,用于处理器安全状态与非安全状态的切换,Hypervisor(hyp)模式则用于对虚拟化有关功能的支持。有关安全状态的详细内容在后续的文章中会介绍。

03

ARM架构中的执行状态

ARMv8-A有两种执行模式,一种是AArch64执行模式,另一种是AArch32执行模式。执行状态定义处理单元(Processing Element, PE)的执行环境,包括以下内容:

  1. 支持的寄存器宽度
  2. 支持的指令集
  3. 异常模型
  4. 虚拟存储系统(Virtual Memory System Architecture, VMSA)架构
  5. 程序员模型

AArch64为64位执行状态。对应上述内容,此执行状态:

  1. 提供31个64位通用寄存器,其中X30用作过程链接寄存器(ProcedureLink Register)。
  2. 提供64位程序计数器(PC)、堆栈指针(SP)和异常链接寄存器(ELRs)。
  3. 提供32个128位寄存器以支持SIMD矢量和标量浮点运算。
  4. 提供单一指令集A64。
  5. 定义ARMv8异常模型,该模型最多有四个异常级别EL0-EL3,它们提供执行权限层次结构。
  6. 支持64位虚拟寻址。
  7. 定义一系列与PSTATE相关的寄存器。A64指令集包括能直接操作各种PSTATE寄存器的指令。
  8. 使用后缀命名每个系统寄存器,该后缀指示可以访问寄存器的最低异常级别。

AArch32为32位执行状态。对应上述内容,此执行状态:

  1. 提供13个32位通用寄存器和一个32位PC、一个32位SP寄存器和一个32位链接寄存器(Link Register,LR)。链接寄存器用作异常链接寄存器和过程链接寄存器。其中一些寄存器有多个备份寄存器,用于不同的处理器工作模式。我们在上一期提到过,同一个功能的寄存器在不同的处理器运行模式下可能对应不同的物理寄存器,这些寄存器被称为备份寄存器。
  2. 为从Hyp(hypervisor)模式返回的异常提供一个异常链接寄存器。
  3. 提供32个64位寄存器,用于对高级SIMD矢量和标量浮点计算的支持。
  4. 提供两个指令集,A32和T32。
  5. 支持基于处理器工作模式的ARMv7-A异常模型,并将其映射到基于异常级别的ARMv8异常模型。
  6. 使用32位虚拟地址。
  7. 使用单个当前程序状态寄存器(CPSR)保存处理器状态。
  8. 在AArch64和AArch32执行状态之间进行转换称为内部处理(interprocessing)。

04

ARMv8-A架构的异常级别和安全状态

ARMv8-A有四个异常级别,从EL0到EL3。对于异常级别ELn,整数n增加表示软件执行的特权权限变大了。EL0级别下的执行叫非特权执行(unprivileged execution)。EL1主要用于运行操作系统内核。EL2可以支持非安全操作的虚拟化。EL3则支持安全状态和非安全状态之间的转换。安全状态与ARM TrustZone技术有关[2]。安全状态可以运行可信执行环境(TEE, Trusted Execution Environment)及安全应用,用于保障隐私数据和程序运行环境的安全性。

ARMv8-A架构并未直接指定哪些软件应该运行在哪些异常级别,但是在通常情况下,有如异常级别的使用模型:

1.应用程序运行在EL0;

2.操作系统内核和相关功能运行在EL1;

3.Hypervisor[3]运行在EL2;

4.安全世界状态和正常世界状态的切换在EL3完成。

下图反映了ARM-v8A架构中的执行状态、安全状态和异常级别之间关系[1]:

从图中我们可以看出,Hypervisor相关的支持特性主要是在EL2的非安全状态实现的。Hypervisor可以支持虚拟机之间的切换,而虚拟机主要被包含在EL1的非安全状态和EL0的非安全状态中。一些Guest OS可以运行在EL1状态里,每一个Guest OS可以运行在一个虚拟机上。而应用则运行在EL0的非安全状态中,同时也运行在Guest OS上。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/tUiJ42TRpul9RhYQLH-UFA

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237287次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8126次阅读
 目录