汇编语言变量.md

原始源文件

---
ingested: true
ingestedAt: 2026-05-17
---
标题: 汇编语言 - 变量
UP主: 菜鸟教程
链接: https://www.runoob.com/assembly/assembly-variables.html
提取方式: WebFetch
内容: ## 汇编语言 - 变量

变量是程序中存储数据的基本单元。在汇编语言中定义和使用变量比高级语言更接近底层,你需要直接控制变量的大小、类型和内存布局。

---

## 汇编中的变量概念

在汇编语言中,变量 本质上是内存中一个有名字的存储位置。

与高级语言不同,汇编变量没有自动的类型检查——一个标签只是内存地址的别名,你可以用任何大小去读写它。

NASM 提供了三种段来存放不同类型的变量:`.data`(已初始化)、`.bss`(未初始化)和 `.rodata`(只读)。

---

## 在 .data 段定义已初始化变量

使用 DB、DW、DD、DQ、DT 伪指令定义不同大小的变量:

| 伪指令 | 数据大小  | 含义                | 示例                             |
| --- | ----- | ----------------- | ------------------------------ |
| DB  | 1 字节  | Define Byte       | flag db 1                      |
| DW  | 2 字节  | Define Word       | count dw 1000                  |
| DD  | 4 字节  | Define Doubleword | price dd 9999                  |
| DQ  | 8 字节  | Define Quadword   | big\_val dq 0x1234567890ABCDEF |
| DT  | 10 字节 | Define Ten Bytes  | ext\_val dt 3.14               |

## 实例

; 文件路径:variables\_data.asm  
; 演示 .data 段中各种变量的定义

section .data  
; 字节变量  
 status db 1 ; 1 字节,值为 1  
 grade db 'A' ; 1 字节,字符 'A' = 0x41

; 字变量(2 字节)  
 year dw 2026 ; 2 字节,值为 2026

; 双字变量(4 字节)  
 salary dd 50000 ; 4 字节,值为 50000

; 多字节序列  
 msg db 'Hello, runoob!', 0 ; 字符串以 0 结尾(C 风格)  
 hex\_bytes db 0x55, 0xAA, 0x00, 0xFF ; 十六进制字节序列

; 重复值  
 stars db 10 dup('\*') ; 10 个星号字符

; 带名称的多个变量  
 x dd 10  
 y dd 20  
 z dd 30

section .text  
global \_start

\_start:  
; 读取变量值到寄存器  
mov al, \[status\] ; al = 1(读取 1 字节)  
mov ax, \[year\] ; ax = 2026(读取 2 字节)  
mov eax, \[salary\] ; eax = 50000(读取 4 字节)

; 修改变量值  
mov byte \[status\], 0 ; status = 0  
mov dword \[x\], 100 ; x = 100

mov eax, 1  
mov ebx, 0  
int 0x80  

> 使用 `[变量名]` 访问变量时,务必确保读取/写入的字节数与变量定义时的字节数匹配。用 `mov al, [status]` 读 1 字节,用 `mov eax, [salary]` 读 4 字节。NASM 会检查操作数大小是否一致。

---

## 在 .bss 段预留未初始化空间

使用 RESB、RESW、RESD 等伪指令预留空间(不初始化):

| 伪指令  | 预留大小    | 示例              |
| ---- | ------- | --------------- |
| RESB | 字节      | buffer resb 256 |
| RESW | 字(2字节)  | wbuf resw 100   |
| RESD | 双字(4字节) | dbuf resd 50    |
| RESQ | 四字(8字节) | qbuf resq 25    |

## 实例

; 文件路径:variables\_bss.asm  
; 演示 .bss 段中预留空间

section .bss  
 input\_buf resb 128 ; 预留 128 字节的输入缓冲区  
 numbers resd 100 ; 预留 100 个双字(400 字节)  
 temp resb 1 ; 预留 1 字节的临时变量

section .data  
 prompt db 'Enter a number: '  
 prompt\_len equ $ \- prompt

section .text  
global \_start

\_start:  
; 输出提示  
mov eax, 4  
mov ebx, 1  
mov ecx, prompt  
mov edx, prompt\_len  
int 0x80

; 读取输入到 .bss 段的缓冲区  
mov eax, 3  
mov ebx, 0  
mov ecx, input\_buf ; 使用 .bss 段预留的空间  
mov edx, 128  
int 0x80

; 向 numbers 数组填入数据  
mov dword \[numbers\], 42 ; numbers\[0\] = 42  
mov dword \[numbers + 4\], 100 ; numbers\[1\] = 100

mov eax, 1  
mov ebx, 0  
int 0x80  

---

## 字节、字、双字的内存布局

x86 使用 小端序(Little Endian)——低字节存放在低地址。

例如,当定义 `value dd 0x12345678` 时,内存中的布局为:

地址    :[value]  [value+1]  [value+2]  [value+3]
内容    :0x78     0x56       0x34       0x12

## 实例

; 文件路径:endianness.asm  
; 演示小端序存储

section .data  
 value dd 0x12345678 ; 双字,4 字节

section .text  
global \_start

\_start:  
; 按不同大小读取同一个变量  
mov eax, \[value\] ; 读 4 字节:eax = 0x12345678  
mov ax, \[value\] ; 读 2 字节:ax = 0x5678(低2字节)  
mov al, \[value\] ; 读 1 字节:al = 0x78(最低1字节)

; 验证小端序:低地址存放低字节  
mov al, \[value\] ; al = 0x78  
mov bl, \[value + 1\] ; bl = 0x56  
mov cl, \[value + 2\] ; cl = 0x34  
mov dl, \[value + 3\] ; dl = 0x12

mov eax, 1  
mov ebx, 0  
int 0x80  

---

## 变量的初始化与访问

汇编中变量的操作遵循"加载-运算-存储"三步模式:

## 实例

; 文件路径:var\_operations.asm  
; 演示变量操作的三步模式

section .data  
 a dd 100  
 b dd 200  
 result dd 0

section .text  
global \_start

\_start:  
; result = a + b  
; 第1步:加载  
mov eax, \[a\] ; 加载 a 到 eax  
; 第2步:运算  
add eax, \[b\] ; eax = eax + b  
; 第3步:存储  
mov \[result\], eax ; 存储结果到 result

; result = a \* 2 - b  
mov eax, \[a\]  
imul eax, 2 ; eax = a \* 2  
sub eax, \[b\] ; eax = eax - b  
mov \[result\], eax

mov eax, 1  
mov ebx, 0  
int 0x80  

> 汇编不支持 `mov [result], [a] + [b]` 这种高级语法。x86 的 mov 指令不能同时用两个内存操作数,必须先经过寄存器中转。

---

## 变量大小操作符

当汇编器无法推断操作数大小时,需要显式指定:

## 实例

; 使用大小操作符明确数据大小

section .data  
 var dd 0

section .text  
global \_start

\_start:  
; 大小操作符:byte, word, dword, qword  
mov byte \[var\], 1 ; 写入 1 字节  
mov word \[var\], 1000 ; 写入 2 字节  
mov dword \[var\], 999999 ; 写入 4 字节

; 当目标大小明确时(由寄存器决定),可以省略  
mov al, \[var\] ; al 是 1 字节,自动按 byte 读取  
mov ax, \[var\] ; ax 是 2 字节,自动按 word 读取  
mov eax, \[var\] ; eax 是 4 字节,自动按 dword 读取

; 但下面这行会报错(大小不明确):  
; mov \[var\], 1 ; 错误!1 可以是字节/字/双字  
; 必须写成:  
mov dword \[var\], 1 ; 明确指定 4 字节

mov eax, 1  
mov ebx, 0  
int 0x80