汇编语言 - 基础语法

汇编语言 - 基础语法

汇编语言 - 基础语法

本章介绍 NASM 汇编程序的基本结构、语法规则和书写规范,帮助你理解汇编代码的骨架。

汇编程序的基本结构

一个完整的 NASM 汇编程序通常由以下几个部分组成:

实例

; 文件路径:structure.asm

; NASM 程序基本结构示例

section .data ; 数据段:存放已初始化的数据

; 这里定义变量和常量

msg db 'Hello, RUNOOB!', 0xA

len equ $ - msg

section .bss ; BSS 段:存放未初始化的数据

; 这里预留内存空间

buffer resb 64 ; 预留 64 字节的缓冲区

section .text ; 代码段:存放可执行指令

global _start

_start:

; 这里写程序逻辑

mov eax, 4

mov ebx, 1

mov ecx, msg

mov edx, len

int 0x80

mov eax, 1

mov ebx, 0

int 0x80

段(Section)用途特点

.data存放已初始化的全局变量和常量编译时确定大小和内容,存入可执行文件

.bss存放未初始化的全局变量只在运行时分配空间,不占用可执行文件大小

.text存放可执行的机器指令只读,包含程序的全部逻辑代码

至少需要 .text 段才能构成一个有效的汇编程序。如果没有数据,可以省略 .data 和 .bss 段。

汇编语句格式

每条汇编语句的通用格式为:

[标签:] 指令助记符 [操作数1 [, 操作数2 [, 操作数3]]] [; 注释]

各部分说明:

部分是否必须说明

标签(Label)可选代表一个内存地址的符号名,以冒号结尾

指令助记符必须如 mov、add、sub 等,告诉 CPU 要做什么

操作数可选(部分指令无操作数)指令操作的数据对象,可为寄存器、内存地址、立即数

注释可选以分号开头,一直延续到行尾

实例

; 各种语句格式示例

; 只有指令,无操作数

ret ; 从子程序返回

; 指令 + 单个操作数

push eax ; 将 eax 的值压入栈中

inc ecx ; ecx 加 1

; 指令 + 两个操作数(最常见)

mov eax, 42 ; 将 42 复制到 eax 寄存器

add ebx, ecx ; ebx = ebx + ecx

; 带有标签

loop_start: ; 标签:标记循环开始位置

dec ecx ; ecx 减 1

jnz loop_start ; 如果 ecx 不为 0,跳回 loop_start

注释规范

NASM 使用 分号(;) 表示注释,从分号到行尾的内容都会被汇编器忽略。

实例

; 整行注释:说明下面代码块的用途

; 计算两个数的和并输出结果

mov eax, 10 ; 行内注释:将 10 放入 eax

add eax, 20 ; 行内注释:将 20 加到 eax,现在 eax = 30

汇编代码中注释极其重要。没有注释的汇编代码过几周连作者自己都可能看不懂。养成每条指令都写注释的习惯。

标识符命名规则

标识符(标签、变量名、常量名等)须遵循以下规则:

规则说明

组成字符字母、数字、下划线 _、点 .、问号 ?、@、$、# 等

起始字符必须以字母、下划线、点或问号开头,不能以数字开头

大小写默认区分大小写(可通过编译选项修改)

保留字不能和指令助记符、寄存器名或 NASM 关键字重名

实例

; 合法的标识符

my_variable: ; 字母开头 + 下划线

.loop_start: ; 点开头(局部标签)

?error_handler: ; 问号开头

counter2: ; 字母 + 数字

; 不合法的标识符(仅供参考,不要使用)

; 1st_value: ; 错误:不能以数字开头

; mov: ; 错误:mov 是保留字

; my-variable: ; 错误:减号不是合法字符

伪指令(Directives)

伪指令 是给汇编器的命令,不是给 CPU 的指令,用于控制汇编过程和定义数据结构。

伪指令用途示例

db定义字节(1 字节)byte_val db 0x55

dw定义字(2 字节)word_val dw 0x1234

dd定义双字(4 字节)dword_val dd 0x12345678

equ定义常量MAX_SIZE equ 256

resb预留字节空间buffer resb 128

resw预留字空间wbuf resw 64

resd预留双字空间dbuf resd 32

%define宏定义常量%define COUNT 10

大小写规范

NASM 默认对标签和标识符 区分大小写:

实例

; 大小写敏感的示例

section .data

msg db 'RUNOOB', 0 ; 定义变量 msg

section .text

global _start

_start:

mov eax, MSG ; 错误:MSG 和 msg 不同(除非开启忽略大小写)

mov eax, msg ; 正确:msg 与定义完全一致

MOV EAX, 42 ; 语法正确:指令助记符不区分大小写

mov eax, 42 ; 推荐写法:用小写,可读性更好

指令助记符和寄存器名不区分大小写(MOV、Mov、mov 效果相同),但推荐的风格是统一小写。

数值表示方式

NASM 支持多种进制的数值表示:

实例

; NASM 中不同进制的表示方式

mov eax, 42 ; 十进制:直接写数字

mov eax, 0x2A ; 十六进制:0x 前缀(推荐写法)

mov eax, 2Ah ; 十六进制:h 后缀

mov eax, 0o52 ; 八进制:0o 前缀

mov eax, 52o ; 八进制:o 后缀

mov eax, 101010b ; 二进制:b 后缀

mov eax, 0b101010 ; 二进制:0b 前缀

推荐使用 0x 前缀表示十六进制(如 0x2A),这样不容易和标签混淆。

一个完整的语法示例

下面程序综合运用以上语法元素,计算 1 到 10 的和并输出:

实例

; 文件路径:sum.asm

; 计算 1+2+...+10 并输出结果字符

section .data

result db 0 ; 存放计算结果(1字节)

newline db 0xA ; 换行符

section .text

global _start

_start:

; 初始化寄存器和变量

mov ecx, 10 ; 循环计数器:从 10 开始倒数

mov eax, 0 ; eax 存放累加和,初始为 0

sum_loop: ; 循环开始标签

add eax, ecx ; eax = eax + ecx

dec ecx ; ecx 减 1

jnz sum_loop ; 如果 ecx != 0,继续循环

; 此时 eax = 55(10+9+...+1)

add eax, '0' ; 将数字转为 ASCII 字符('0'=48,55+48=103='g',不对)

; 实际演示需要更复杂的转换,见后续章节

; 这里只输出 result(简化演示)

mov [result], al ; 将累加结果存入 result

; 退出程序

mov eax, 1

mov ebx, 0

int 0x80

注意:上面的示例中,直接加 '0' 只在数字是 0-9 范围内正确。处理两位数及以上的数字转换,将在后续章节详细讲解。

相关推荐

岫岩皮影戏简介
bt365网站

岫岩皮影戏简介

📅 07-11 👁️ 2219
樱桃酒可以放多久 樱桃泡酒要去核吗
mobile365体育

樱桃酒可以放多久 樱桃泡酒要去核吗

📅 08-03 👁️ 2455
pia戏是什么意思,配音圈术语科普,声控文化入门指南
冻雨试验都检测哪些项目?能用到哪些设备?详细过程是怎样的?
东北人都是吃啥主食长大的?
mobile365体育

东北人都是吃啥主食长大的?

📅 09-23 👁️ 517
《波西米亚狂想曲》之后,我发现了更疯狂的牙叔
best365官网体育投注

《波西米亚狂想曲》之后,我发现了更疯狂的牙叔

📅 06-29 👁️ 168