C 语言学习(5) ---- 汇编语法基础

目录

        • 汇编语言基础
        • [x86 体系的寄存器说明](#x86 体系的寄存器说明)
        • [Intel 和 AT&T 语法](#Intel 和 AT&T 语法)
        • ["helloworld" 汇编程序分析](#"helloworld" 汇编程序分析)
        • 指令和伪指令
        • TBD
汇编语言基础

汇编程序基本由 4 种类型的组件组成:指令(instruction)伪指令(directive)、标号(label)以及注释(comment)

类型 示例 含义
指令 mov eax 0 给 EAX 赋值为0
伪指令 .section.text 以下代码放入 text 节
伪指令 .string "foobar" 定义一个 ASCII 字符串 foobar
伪指令 .long 0x12345678 定义一个双字 0x12345678
标号 foo:.string "foobar" 使用符号定义的 foobar 字符串
注释 #注释 表示注释信息
x86 体系的寄存器说明

在 x86 架构的 CPU 中,存在多种可编程的寄存器,它们用于不同的目的,以下是一些主要的可编程寄存器类型:

  1. 通用寄存器
    • AX (累加器寄存器):用于算术运算和 I/O 指令。
    • BX (基址寄存器):用于存储数据指针。
    • CX (计数寄存器):通常用于循环计数。
    • DX (数据寄存器):用于 I/O 操作和其他数据传输。
    • SI (源索引寄存器)、DI (目的索引寄存器):用于字符串操作。
    • BP (基址指针寄存器):用于访问栈中的参数和局部变量。
    • SP (堆栈指针寄存器):用于管理堆栈。
    • AXBXCXDX 寄存器还可以分为高字节和低字节寄存器,例如 AHAL 分别是 AX 的高字节和低字节。

EAX 是一个32位的寄存器,用于处理 32 位的数据,而 AX 是一个 16 位的寄存器,用于处理 16 位的数据。

在32位模式下,AXEAX 的一个低位部分,可以直接用于 16 位数据的操作。

x86 基于原始的 8086 指令集,寄存器是16位宽,而32bit 的 x86 ISA 将这些寄存区扩展为32位,然后 x86-64 将它们进一步扩展为64位。

为了保证向后兼容性,新指令集中使用的寄存器是旧的寄存器的超集。

在汇编中指定寄存器的操作数,需要是以寄存器的名称,比如 mov rax,64 就是将 64 赋值给 rax 寄存器,

下图显示了如何将 x86-64 rax 寄存器分为传统的 32 位和 64 位寄存器,rax 的低32位形成了一个名位 eax 的寄存器,

其低16位形成了一个原始的 8086 寄存器 AX,读者可以通过寄存器名称 AL 访问 AX 的低字节,通过 AH 访问 AX 的高字节

同样的,其他的通用寄存器,也会与类似的用法:

描述 64bit 低32bit 0~16 bit 8~16 bit 0~8 bit
累加器 rxa eax ax ah al
基址寄存器 rbx ebx bx bl bh
程序计数器 rcx ecx cx cl ch
数据寄存器 rdx edx dx dl dh
  1. 段寄存器

    • CS (代码段寄存器):包含当前执行指令的段地址。
    • DS (数据段寄存器):包含数据段的段地址。
    • ES (附加段寄存器):用于额外的数据段。
    • FSGS:提供额外的段寄存器,由操作系统或应用程序定义。
    • SS (堆栈段寄存器):包含堆栈段的段地址。
  2. 指令指针寄存器

    • IP (指令指针寄存器):也称为 EIP(在 32 位模式下)或 RIP(在 64 位模式下),它指向下一条要执行的指令。
      本质上就是指针指针寄存器
  3. 标志寄存器

    • FLAGS (标志寄存器):包含各种状态标志,如进位、零、符号、溢出等。
  4. 控制寄存器

    • CR0 - CR4:用于控制处理器的操作模式和特性,如分页、保护模式等。
  5. 系统寄存器

    • MSR (模型特定寄存器):提供对处理器特定功能的访问,如性能监控计数器。
  6. 浮点寄存器

    • ST0 - ST7 (浮点堆栈寄存器):用于浮点运算。
    • Control WordStatus WordTag WordInstruction PointerLast Instruction Opcode:用于控制浮点单元的操作和报告状态。
  7. SIMD 寄存器

    • MMX 寄存器:用于多媒体扩展运算。
    • XMM0 - XMM15 (SSE 寄存器):用于 SIMD 扩展运算。
    • YMM0 - YMM15 (AVX 寄存器):在 AVX 指令集中使用,提供更大的 SIMD 数据宽度。
      这些寄存器在不同的 x86 处理器模式下(实模式、保护模式、长模式等)可能会有不同的名称和大小。
      例如,在 32 位模式下,通用寄存器通常有 32 位宽,而在 64 位模式下,它们会扩展到 64 位宽。
Intel 和 AT&T 语法

正如前面所提到的,不同的汇编器对汇编程序有不同的语法,表示 x86 机器指令的语法格式主要有两种:Intel 语法 和 AT&T 语法,
AT&T 语法显式的再每个寄存器名称前面加上 % 符号,每个常量前面加上$ 符号, Intel 语法没有这种格式:

AT&TIntel之间最重要的区别是使用完全相反的指令操作数顺序:

AT&T语法中源操作数在目的操作数前面,所以是从左向右读

Intel语法中目的操作数位于源操作数前面,所以是从右向左读
如果汇编语言中出现 % 和 $ 前缀,就是使用AT&T语法,应该从左向右读

"helloworld" 汇编程序分析

helloworld 的汇编代码:

c 复制代码
  1         .file   "main.c"
  2         .text
  3         .section        .rodata
  4 .LC0:
  5         .string "hello world"
  6         .text
  7         .globl  main
  8         .type   main, @function
  9 main:
 10 .LFB0:
 11         .cfi_startproc
 12         endbr64
 13         pushq   %rbp
 14         .cfi_def_cfa_offset 16
 15         .cfi_offset 6, -16
 16         movq    %rsp, %rbp
 17         .cfi_def_cfa_register 6
 18         leaq    .LC0(%rip), %rdi
 19         call    puts@PLT
 20         movl    $0, %eax
 21         popq    %rbp
 22         .cfi_def_cfa 7, 8
 23         ret
 24         .cfi_endproc
 25 .LFE0:
 26         .size   main, .-main
 27         .ident  "GCC: (Ubuntu 9.5.0-1ubuntu1~22.04) 9.5.0"
 28         .section        .note.GNU-stack,"",@progbits
 29         .section        .note.gnu.property,"a"
 30         .align 8
 31         .long    1f - 0f
 32         .long    4f - 1f
 33         .long    5
 34 0:
 35         .string  "GNU"
 36 1:
 37         .align 8
 38         .long    0xc0000002
 39         .long    3f - 2f
 40 2:
 41         .long    0x3
 42 3:
 43         .align 8
 44 4:

从中可以看出:

  • printf 函数最终是调用到 puts 执行打印 helloworld 的操作
  • main 函数的返回值是通过 EAX 传递的
  • 函数执行时会将当前 rbp 寄存器的值压入到堆栈中,然后将当前开辟的 rsp的值赋给它
  • 函数执行结束会弹出 rbp 寄存器的值
指令和伪指令

指令是 CPU 执行的实际操作,伪指令意在告诉汇编工具生成特定的数据,并将指令和数据放在指定的节,
标号是汇编工具中引用指令或数据的符号名称,注释是可读注释。在程序被汇编链接成二进制程序后,所有的符号名称都被地址所取代

伪指令:
.section 告诉汇编工具将在那个节放置后面的内容,
.ascii 表示定义 ascii 字符串的伪指令,当前还有一些伪指令用于定义其他数据类型:
.byte 一个字节
.word 两个字节
.long 四个字节
.quad 八个字节

TBD
相关推荐
王俊山IT12 分钟前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??1 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
Mephisto.java1 小时前
【大数据学习 | kafka高级部分】kafka中的选举机制
大数据·学习·kafka
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY2 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若2 小时前
C语言比较两个字符串是否相同
c语言
武子康3 小时前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
使者大牙3 小时前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
As977_3 小时前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习