NASM:80x86汇编语言编译器

一、NASM简介

1. 定义与特点

NASM(Netwide Assembler)是一款为可移植性与模块化而设计的80x86的汇编器。

具有高可移植性,能在多种操作系统(如Windows、Linux、Unix等)和硬件平台上运行。其语法简洁,类似于Intel语法但更简化,易于学习。

支持多种目标文件格式,像Linux、NetBSD和FreeBSD的a.out、elf和coff格式,微软16位的obj格式和win32格式,还可输出纯二进制文件。

指令集支持全面,涵盖“pentium”“p6”“mmx”“3dnow!”“sse”和“sse2”等指令集,可充分发挥现代处理器性能优势,并且宏命令支持良好,便于代码复用和扩展。

2. 与其他汇编器的区别

与MASM相比,NASM的语法更加简洁直观。例如,在数据定义方面,NASM不需要像MASM那样使用复杂的类型定义前缀,使得代码编写更加简洁。

与GAS(GNU Assembler)不同,NASM的语法更接近Intel风格,对于习惯Intel语法的开发者来说更容易上手。

二、NASM实例

(一)简单的“Hello, World!”程序

1. Linux环境下的实例

以下是一个在Linux环境下使用NASM编写的简单“Hello, World!”程序的步骤:

编写源代码(hello.asm)

section .data
msg db 'Hello, World!',0xa     ; 定义要输出的字符串,0xa是换行符
len equ $ - msg               ; 计算字符串的长度
section .text
global _start
_start:
; 调用系统调用write(系统调用号为4)
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
; 调用系统调用exit(系统调用号为1)
mov eax, 1
xor ebx, ebx
int 0x80

编译与运行

首先使用NASM进行汇编:nasm -f elf32 hello.asm(这里假设编译为32位的ELF格式,如果是64位系统且要编译64位程序,可以使用nasm -f elf64)。

然后使用链接器进行链接:ld -m elf_i386 -s -o hello hello.o(如果是64位程序,链接命令会有所不同,例如ld -o hello hello.o)。

最后运行程序:./hello。

2. Windows环境下的实例(使用Cygwin或MinGW)

编写源代码(hello.asm)

section .data
msg db 'Hello, World!',0dh,0ah,'$' ; 0dh和0ah是回车换行符,'$'是用于DOS输出函数的结束标志
section .text
global _main
_main:
mov ah, 9
mov dx, msg
int 21h
mov ah, 4ch
int 21h

编译与运行

在Cygwin或MinGW环境下,先使用NASM进行汇编:nasm -f win32 hello.asm。

然后使用链接器(如ld)进行链接,生成可执行文件。

在Windows命令提示符下运行生成的可执行文件。

(二)计算两个整数之和的程序

1. 程序代码

section .data
num1 dd 10
num2 dd 20
result dd?
section .text
global _start
_start:
mov eax, [num1]
add eax, [num2]
mov [result], eax

; 以下部分是为了在Linux下以十六进制形式输出结果(可选部分)

mov ebx, eax
mov ecx, 8
mov edi, result
print_hex:
    rol ebx, 4
    mov al, bl
    and al, 0fh
    add al, 30h
    cmp al, 39h
    jbe not_letter
    add al, 7
not_letter:
    mov [edi], al
    inc edi
    loop print_hex
    mov eax, 1
    xor ebx, ebx
    int 0x80

2. 解释

在数据段(section .data)中,定义了两个整数num1和num2,并定义了一个用于存储结果的变量result。

在代码段(section .text)中,首先将num1的值加载到eax寄存器,然后使用add指令加上num2的值,最后将结果存储到result变量中。后面的代码部分(从mov ebx, eax开始)是将结果以十六进制形式输出(这部分主要是为了展示在汇编中如何进行简单的输出处理,并且是针对Linux环境下的一种简单处理方式,如果是在Windows环境下,可以使用不同的输出方法)。

64位汇编语言基础