C/C++汇编学习(三)——指令集-汇编基础

发布时间:2024年01月04日

????????汇编语言是一种用于与计算机硬件直接交互的低级编程语言。它非常接近机器语言,但提供了更易于理解的符号来表示机器指令和数据。不同的处理器架构有不同的汇编语言。例如,x86架构用于大多数个人电脑,而ARM架构常见于移动设备。

目录

1. 指令集

x86 指令集

1. 数据处理指令

2. 数据传输指令

3. 控制流指令

4. 字符串和重复操作指令

5. 位操作指令

6. 特殊和系统指令

7. SIMD指令

ARM 指令集

1. 数据处理指令

2. 数据传输指令

3. 分支指令

4. 条件执行指令

5. 浮点和SIMD指令

6. 特殊指令

7. 控制寄存器指令

指令分类

1. 数据处理指令

2. 数据传输指令

3. 控制流指令

4. 特殊指令

5. SIMD和浮点指令

6. 状态和控制寄存器操作

7. 字符串和重复操作指令

2. 寄存器

1. 通用寄存器

2. 指令指针寄存器

3. 栈指针寄存器

4. 标志寄存器

5. 特殊寄存器

3. 基本的汇编指令

1. MOV 指令

2. ADD 指令

3. SUB 指令

4. 分支和循环

5. 栈操作

6. 函数调用和返回

7. 内联汇编

总结


1. 指令集

????????指令集是一组基本操作,由特定的处理器架构定义。这些操作包括数据处理、数据传输、逻辑操作和控制流指令。每种架构都有其独特的指令集,例如x86和ARM的指令集就大不相同。

x86 指令集

x86 指令集主要用于个人电脑和服务器,是最广泛使用的指令集之一。其特点包括:

  • 富含指令的集合:x86 指令集包含大量的指令,涵盖了从基本的数学运算到复杂的系统调用和硬件控制等多种操作。
  • 复杂指令集计算机(CISC):x86 属于CISC架构,意味着它包含一些执行多个低级操作的复杂指令。
  • 可变长度指令:x86指令的长度不固定,这使得指令集在设计上更为灵活,但也增加了解码指令的复杂性。
  • 支持多种寻址模式:x86 指令集提供多种数据寻址方式,如直接寻址、间接寻址、基址加偏移寻址等。

1. 数据处理指令

这些指令用于执行基本的数学和逻辑运算。

  • ADD, SUB, MUL, DIV:分别用于加法、减法、乘法和除法运算。
  • INC, DEC:分别用于将操作数递增和递减。
  • AND, OR, XOR, NOT:逻辑运算指令,分别执行与、或、异或和非操作。

2. 数据传输指令

用于在寄存器、内存和I/O端口之间移动数据。

  • MOV:将数据从一个位置移动到另一个位置。
  • PUSH, POP:用于操作堆栈,分别是入栈和出栈操作。
  • IN, OUT:用于与I/O端口通信。

3. 控制流指令

这些指令控制程序的执行流程。

  • JMP:无条件跳转到指定地址。
  • JE, JNE, JG, JL 等:条件跳转指令,根据比较结果跳转。
  • CALL, RET:分别用于函数调用和从函数返回。

4. 字符串和重复操作指令

用于处理字符串和重复操作。

  • MOVS, CMPS, SCAS:用于字符串移动、比较和扫描。
  • REP, REPE, REPNE:重复执行字符串操作指令。

5. 位操作指令

用于位级操作。

  • SHL, SHR:分别是逻辑左移和逻辑右移。
  • ROL, ROR:分别是循环左移和循环右移。

6. 特殊和系统指令

  • INT:产生软件中断。
  • NOP:无操作。
  • HLT:停止处理器的执行,直到下一个外部中断。

7. SIMD指令

  • 例如 SSE, SSE2, AVX 系列指令,用于同时处理多个数据。

ARM 指令集

ARM 指令集广泛用于移动设备、嵌入式系统和最近的一些个人电脑。其特点包括:

  • 简单指令集计算机(RISC):ARM 属于RISC架构,指令集较为简单,每条指令通常只执行一个操作。
  • 固定长度指令:大多数ARM指令长度固定,这简化了指令流的解析和执行。
  • 高能效:ARM架构注重能效比,适用于电池供电的设备。
  • 条件执行指令:ARM指令集支持条件执行,这可以减少分支指令的使用,提高程序的效率。

1. 数据处理指令

这些指令用于执行基本的数学和逻辑运算。

  • ADD, SUB:加法和减法。
  • MUL, DIV:乘法和除法。
  • AND, ORR, EOR, BIC:逻辑与、或、异或和位清除。

2. 数据传输指令

用于在寄存器、内存之间移动数据。

  • LDR, STR:加载和存储指令。
  • LDM, STM:加载和存储多个寄存器的内容。

3. 分支指令

控制程序的流程。

  • B, BL:无条件分支和带链接的分支(用于函数调用)。
  • BX, BLX:跳转到寄存器中地址的指令。

4. 条件执行指令

ARM的特色之一,可以在特定条件下执行指令。

  • 指令后缀如 EQ, NE, GT, LT 等,表示等于、不等于、大于、小于等条件。

5. 浮点和SIMD指令

用于浮点计算和单指令多数据操作。

  • VADD, VSUB, VMUL, VDIV:浮点加法、减法、乘法和除法。
  • VMLA, VMLS:浮点乘加和乘减。

6. 特殊指令

  • SVC(原 SWI):用于发起软件中断。
  • NOP:无操作。
  • WFI, WFE:等待中断和等待事件。

7. 控制寄存器指令

用于控制程序状态寄存器。

  • MRS, MSR:用于读取和设置程序状态寄存器。

指令分类

无论是x86还是ARM,其指令集都可以分为以下几类:

  • 数据处理指令:用于算术运算(如加、减)、逻辑运算(如与、或、非)等。
  • 数据传输指令:用于在寄存器、内存和I/O设备之间传输数据。
  • 控制流指令:改变程序执行顺序的指令,如跳转(JMP)、条件分支(如IF-THEN)等。
  • 特殊指令:用于系统调用、中断处理等特殊操作。

1. 数据处理指令

这些指令用于执行各种算术和逻辑运算。

  • 算术指令:如 ADD(加法),SUB(减法),MUL(乘法),DIV(除法)。
  • 逻辑指令:如 AND(与),OR(或),XOR(异或),NOT(非)。
  • 移位指令:如 SHL(左移),SHR(右移),ROR(循环右移),ROL(循环左移)。

2. 数据传输指令

用于在不同位置之间传输数据。

  • 寄存器间传输:如 MOVPUSHPOP
  • 内存访问:如 LDRSTR(ARM),LOADSTORE(x86)。
  • I/O操作:如 INOUT(x86特有)。

3. 控制流指令

控制程序执行的流程。

  • 跳转指令:如 JMPCALLRET
  • 条件分支:如 JE(如果等于则跳转),JNE(如果不等于则跳转)等。
  • 循环控制:如 LOOPJLE(如果小于或等于则跳转)。

4. 特殊指令

用于特定的操作和处理器控制。

  • 系统调用和中断:如 INTSYSCALL
  • 特权指令:如用于控制处理器状态的 STI(设置中断标志),CLI(清除中断标志)。
  • 无操作指令:如 NOP

5. SIMD和浮点指令

处理向量和浮点数。

  • 单指令多数据(SIMD)操作:如 SSEAVX 指令集(x86);NEON(ARM)。
  • 浮点运算:如 FADDFSUBFMUL

6. 状态和控制寄存器操作

用于管理处理器状态。

  • 标志和控制寄存器操作:如 MSRMRS(ARM),LIDT(x86)。

7. 字符串和重复操作指令

针对字符串和重复数据的高效处理。

  • 字符串操作:如 MOVSCMPS
  • 循环和重复操作:如 REPREPE

2. 寄存器

寄存器是处理器内部的小容量存储位置,用于快速访问重要的数据和指令。每个架构都有一组特定的寄存器,常见的寄存器包括:

  • 通用寄存器:用于存储临时数据和地址。
  • 指令指针寄存器:存储下一条执行指令的地址。
  • 栈指针寄存器:指向当前栈顶的位置。
  • 标志寄存器:包含执行结果的状态信息,如零位、进位位等。

1. 通用寄存器

通用寄存器可用于多种目的,如存储中间计算结果、地址等。在不同的架构中,通用寄存器的数量和用途可能有所不同。

  • x86架构:包括AX, BX, CX, DX等。这些寄存器可以进一步分为高低两部分(如AH和AL是AX的高位和低位)。随着架构的发展,引入了更多的扩展寄存器,如EAX, EBX, ECX, EDX(32位),RAX, RBX, RCX, RDX(64位)。
  • ARM架构:通常有R0到R15等寄存器,其中R13通常用作栈指针(SP),R14作为链接寄存器(LR),R15作为程序计数器(PC)。

2. 指令指针寄存器

指令指针寄存器(Program Counter, PC)存储下一条要执行的指令的地址。

  • x86架构:称为程序计数器(PC)或指令指针(IP)。
  • ARM架构:R15寄存器充当程序计数器。

3. 栈指针寄存器

栈指针寄存器(Stack Pointer, SP)指向当前栈顶的位置。它在函数调用和返回过程中起着重要作用,用于管理函数的调用栈。

  • x86架构:ESP(32位)和RSP(64位)寄存器用作栈指针。
  • ARM架构:R13寄存器通常用作栈指针。

4. 标志寄存器

标志寄存器(Flag Register)用于存储处理器状态、指示指令执行的结果。

  • x86架构:EFLAGS(32位)和RFLAGS(64位)寄存器包含多个标志位,如零标志(ZF)、进位标志(CF)、溢出标志(OF)等。
  • ARM架构:程序状态寄存器(Program Status Registers, PSRs)包括应用程序状态寄存器(APSR)中的标志位,如N(负),Z(零),C(进位),V(溢出)。

5. 特殊寄存器

除了上述常见类型,还有一些特殊用途的寄存器。

  • 段寄存器(x86特有):如CS(代码段寄存器)、DS(数据段寄存器)等,用于支持x86的内存分段机制。
  • 链接寄存器(ARM特有):R14寄存器,用于存储函数调用的返回地址。

3. 基本的汇编指令

汇编语言中常见的基本指令包括:

  • MOV:数据传输指令,用于将数据从一个位置移动到另一个位置。
  • ADD:算术加法指令,用于将两个数值相加。
  • SUB:算术减法指令,用于从一个数值中减去另一个数值。

????????汇编语言确实提供了对硬件的直接控制能力,特别是在需要精确控制硬件行为或优化性能的场景中。下面是x86架构中MOV, ADD, 和 SUB 指令的详细介绍和示例。

1. MOV 指令

??MOV 指令用于将数据从一个位置移动到另一个位置。它不进行任何算术或逻辑操作,仅仅是数据传输。

MOV AX, 5     ; 将立即数 5 移动到 AX 寄存器
MOV BX, AX    ; 将 AX 寄存器中的值复制到 BX 寄存器

2. ADD 指令

??ADD 指令用于将两个数值相加。它是最基本的算术运算指令之一。

MOV AX, 5     ; 将 5 移动到 AX 寄存器
ADD AX, 3     ; 将 AX 寄存器中的值与 3 相加,结果存回 AX

3. SUB 指令

? ?SUB 指令用于从一个数值中减去另一个数值。

MOV AX, 10    ; 将 10 移动到 AX 寄存器
SUB AX, 4     ; 将 AX 寄存器中的值与 4 相减,结果存回 AX

4. 分支和循环

????????在汇编语言中,控制流的操作通常涉及条件分支和循环。这个例子中,CMP 指令用于比较两个寄存器的值,JEJNE 是条件跳转指令,它们根据比较的结果跳转到不同的代码段。

CMP AX, BX       ; 比较 AX 和 BX 的值
JE equal         ; 如果 AX 等于 BX,则跳转到标签 'equal'
JNE notequal     ; 如果 AX 不等于 BX,则跳转到标签 'notequal'
equal:
    ; 在这里编写 AX 等于 BX 时的代码
    JMP end
notequal:
    ; 在这里编写 AX 不等于 BX 时的代码
end:

????????这里,LOOP 指令用于实现循环。它每次迭代都会减少 CX 寄存器的值,并且当 CX 不为 0 时跳回到循环的开始

MOV CX, 5    ; 初始化计数器
loop_start:
    ; 循环体的代码
    LOOP loop_start ; 减少 CX 的值,如果 CX 不为 0,则跳回到 loop_start

5. 栈操作

????????栈是一种重要的数据结构,用于实现函数调用、参数传递等。

PUSH AX       ; 将 AX 寄存器的值压入栈中
PUSH BX       ; 将 BX 寄存器的值压入栈中
POP CX        ; 将栈顶的值弹出到 CX 寄存器

6. 函数调用和返回

????????在汇编中,函数调用涉及将参数放入寄存器或栈中,然后使用 CALL 指令调用函数。

CALL myFunction ; 调用函数
myFunction:
    ; 函数体
    RET           ; 返回

??CALL 指令用于调用函数,RET 指令用于从函数返回。

7. 内联汇编

????????在高级语言(如C或C++)中,内联汇编允许将汇编指令直接嵌入到源代码中。这种方法结合了高级语言的易用性和汇编语言的强大能力。

int a = 10, b = 20, sum;
asm ("MOV %1, %%eax\n\t"
     "ADD %2, %%eax\n\t"
     "MOV %%eax, %0"
     : "=r" (sum)      /* 输出 */
     : "r" (a), "r" (b) /* 输入 */
     : "%eax"           /* 被改变的寄存器 */
    );

????????在这个例子中,asm 关键字用于嵌入汇编代码。该代码将 ab 的值相加,并将结果存储在 sum 中。?

总结

????????汇编语言允许程序员直接操控硬件,理解和操作处理器的内部机制。这在系统编程、嵌入式系统、操作系统开发等领域非常重要。不过,由于汇编语言高度依赖于具体的硬件架构,因此通常不如高级语言(如C++或Python)那样具有可移植性。

文章来源:https://blog.csdn.net/weixin_44120785/article/details/135395187
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。