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

汇编语言基础

汇编程序基本由 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 的高字节
AX寄存器分析
同样的,其他的通用寄存器,也会与类似的用法:

描述64bit低32bit0~16 bit8~16 bit0~8 bit
累加器rxaeaxaxahal
基址寄存器rbxebxbxblbh
程序计数器rcxecxcxclch
数据寄存器rdxedxdxdldh
  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 的汇编代码:

  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
  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值