汇编语句中定义变量

  • GAS(GNU Assembler)

    • 设计目标:GAS 是 GNU 工具链的一部分,设计用于与 GNU 编译器集合(GCC)紧密集成。它支持多种平台和处理器架构,包括 x86、ARM、MIPS 等。
    • 使用场景 :主要用于与 GCC 一起使用,编写嵌入式系统、操作系统内核、以及其他需要与 GCC 集成的低级编程任务。它的设计使得它适合与 GNU 工具链中的其他工具(如 ld 链接器)一起使用。
  • NASM(Netwide Assembler)

    • 设计目标:NASM 是一个专注于 x86 和 x86-64 架构的汇编器,设计简单,语法直观。它强调与现代汇编语言语法的一致性,并提供了丰富的宏功能。
    • 使用场景 :适用于需要对 x86 架构进行细粒度控制的任务,如编写操作系统、引导程序、以及其他需要直接控制硬件的低级编程。它可以单独使用,也可以与不同的工具链一起使用(如使用 ld 链接器或其他链接器)。

GNU 汇编器(GAS)和 NASM 汇编器在定义变量和数据的方式上有一些重要的区别。以下是这两种汇编器在定义变量时的一些主要区别:

1. 数据段(Section)

  • GNU 汇编器(GAS) 使用 .data, .bss, 和 .rodata 段来定义数据。
  • NASM 汇编器 使用 section .data, section .bss, 和 section .rodata 来定义数据。
示例:定义数据段

GAS

cpp 复制代码
.section .data
my_var: .long 0x12345678  ; 定义一个32位整数

.section .bss
uninit_var: .skip 4       ; 预留4字节空间

NASM

cpp 复制代码
section .data
my_var dd 0x12345678      ; 定义一个32位整数

section .bss
uninit_var resb 4         ; 预留4字节空间

2. 数据定义伪指令

  • GNU 汇编器(GAS) 使用 .byte, .short, .long, .quad, .fill 等伪指令。
  • NASM 汇编器 使用 db, dw, dd, dq, resb, resw, resd, resq 等指令。
示例:定义数据

GAS

cpp 复制代码
.section .data
byte_var: .byte 0x1       ; 定义一个字节
short_var: .short 0x1234  ; 定义一个16位整数
long_var: .long 0x12345678 ; 定义一个32位整数

NASM

cpp 复制代码
section .data
byte_var db 0x1           ; 定义一个字节
short_var dw 0x1234       ; 定义一个16位整数
long_var dd 0x12345678    ; 定义一个32位整数

3. 未初始化数据

  • GNU 汇编器(GAS) 使用 .bss 段来定义未初始化的数据。
  • NASM 汇编器 使用 section .bssresb, resw, resd, resq 来预留空间。
示例:未初始化数据

GAS

cpp 复制代码
.section .bss
buffer: .skip 1024         ; 预留1024字节的空间

NASM

cpp 复制代码
section .bss
buffer resb 1024           ; 预留1024字节的空间

4. 只读数据

  • GNU 汇编器(GAS) 使用 .rodata 段来定义只读数据。
  • NASM 汇编器 也使用 section .rodata 来定义只读数据。
示例:只读数据

GAS

cpp 复制代码
.section .rodata
message: .asciz "Hello, World!"  ; 定义一个以0结尾的字符串

NASM

cpp 复制代码
section .rodata
message db 'Hello, World!', 0    ; 定义一个以0结尾的字符串

5. 符号导出

  • GNU 汇编器(GAS) 使用 .global 指令将符号声明为全局。
  • NASM 汇编器 使用 global 指令将符号声明为全局。
示例:定义全局符号

GAS

cpp 复制代码
.section .data
.global my_var
my_var: .long 0x12345678

NASM

cpp 复制代码
section .data
global my_var
my_var dd 0x12345678

总结

  • 数据段声明 :GAS 使用 .section,NASM 使用 section
  • 数据定义伪指令 :GAS 使用 .byte, .short, .long, .fill,NASM 使用 db, dw, dd, resb 等。
  • 未初始化数据 :GAS 使用 .bss,NASM 使用 section .bssresb, resw, resd, resq
  • 只读数据 :GAS 使用 .rodata,NASM 使用 section .rodata
  • 全局符号 :GAS 使用 .global,NASM 使用 global

GAS示例代码:

linkage.h

cpp 复制代码
#ifndef _LINUX_LINKAGE_H
#define _LINUX_LINKAGE_H

#define ENTRY(name) \
  .globl name; \
  ALIGN; \
  name:

#endif

start.S

cpp 复制代码
.text
#include "linkage.h"

.section ".data.pg_dir","w"
ENTRY(swapper_pg_dir)
    .long 100
    .fill 1023,4,0

main.c

cpp 复制代码
#include <stdio.h>

// 声明swapper_pg_dir符号,它在外部定义
extern unsigned int swapper_pg_dir[];

int main() {
    // 输出swapper_pg_dir的地址
    printf("Address of swapper_pg_dir: %p\n", swapper_pg_dir);
    // 访问swapper_pg_dir中的第一个值(应该是0)
    printf("First value in swapper_pg_dir: %u\n", swapper_pg_dir[0]);
    return 0;
}

gcc -c start.S -o start.o
gcc -c main.c -o main.o
gcc start.o main.o -o test

执行结果:

./test

Address of swapper_pg_dir: 0x55e20ee01010

First value in swapper_pg_dir: 100

代码解释

cpp 复制代码
.section ".data.pg_dir","w"
.globl swapper_pg_dir
swapper_pg_dir:
    .long 100
    .fill 1023,4,0
1. .section ".data.pg_dir","w"
  • .section :这条伪指令指定当前段的名称为 .data.pg_dir,并且该段是可写的("w")。如果你使用 ".data" 作为段名,它将是 .data 段的一个变体,但在此示例中,.data.pg_dir 是一个自定义段名。
  • .data 段通常用于已初始化的数据,但自定义名称可以用于组织不同类型的数据。
2. .globl swapper_pg_dir
  • .globl :这条伪指令将 swapper_pg_dir 符号声明为全局符号,使其可以在其他文件或模块中引用。
3. swapper_pg_dir:
  • swapper_pg_dir: :定义了一个标签 swapper_pg_dir,用于在内存中标识数据的开始位置。
4. .long 100
  • .long :将一个32位的整数 100 存储在 swapper_pg_dir 标签所在的内存位置。
5. .fill 1023,4,0
  • .fill :用于在内存中填充数据。
    • 1023:填充的数量,即填充 1023 个 4 字节(总共 4092 字节)的数据。
    • 4:每个填充项的大小,以字节为单位,这里是 4 字节。
    • 0:填充的值,这里是 0。
相关推荐
洛寒瑜2 天前
【读书笔记-《30天自制操作系统》-18】Day19
c语言·开发语言·汇编·笔记·学习·操作系统·文件读取
大山很山2 天前
关于单片机的【汇编指令系统】
汇编·单片机
看星星的派大星3 天前
通过 汇编 分析 结构体
linux·汇编
xiaozhiwise3 天前
ARM 全局变量更换基址寄存器
汇编
halcyonfreed4 天前
2.3.1 协程设计原理与汇编实现coroutine
汇编
看星星的派大星5 天前
第二期: 第三节 裸机代码如何烧写
linux·汇编
c沫栀5 天前
汇编语言第一次作业
汇编
maray7 天前
Dance with Compiler - EP3 ARM64 汇编传参约定以及 restrict 汇编分析
汇编
看星星的派大星8 天前
汇编伪指令 GNU 风格(24)
linux·服务器·汇编·gnu
TeYiToKu8 天前
笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel
linux·c语言·汇编·笔记·单片机·嵌入式硬件