汇编语句中定义变量

  • 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。
相关推荐
დ旧言~9 小时前
实战项目 Boost 搜索引擎
服务器·c语言·前端·网络·汇编·c++
Crossoads5 天前
【汇编语言】call 和 ret 指令(一) —— 探讨汇编中的ret和retf指令以及call指令及其多种转移方式
android·开发语言·javascript·汇编·人工智能·数据挖掘·c#
Crossoads6 天前
【汇编语言】转移指令的原理(三) —— 汇编跳转指南:jcxz、loop与位移的深度解读
android·汇编·人工智能·redis·单片机·深度学习·机器学习
zhuqiyua7 天前
深入解析Kernel32.dll与Msvcrt.dll
汇编·microsoft·windbg·二进制·dll
Crossoads8 天前
【汇编语言】数据处理的两个基本问题(三) —— 汇编语言的艺术:从div,dd,dup到结构化数据的访问
android·linux·运维·服务器·汇编·机器学习·数据挖掘
Crossoads8 天前
【汇编语言】数据处理的两个基本问题(二) —— 解密汇编语言:数据长度与寻址方式的综合应用
android·java·开发语言·javascript·汇编·数据挖掘·c#
Coding~9 天前
逆向攻防世界CTF系列38-xxxorrr
c语言·汇编·安全
Crossoads9 天前
【汇编语言】数据处理的两个基本问题 —— 汇编语言中的数据奥秘:数据位置与寻址方式总结
android·汇编·人工智能·redis·单片机·深度学习·机器学习
Crossoads10 天前
【汇编语言】更灵活的定位内存地址的方法(一)—— 字符操作:and与or指令、ASCII码及大小写转换
android·linux·运维·服务器·汇编·机器学习·数据挖掘
不会写算法的小沈10 天前
函数栈帧的创建与销毁
c语言·汇编·数据结构