汇编

汇编语言主要是 Intel 格式和 AT&T 格式。最常用的是 Intel 格式

Windows 平台 Intel 格式最常用的是两种汇编格式:MASM 和 NASM

《x86汇编语言-从实模式到保护模式》教你如何直接控制硬件,不借助于 BIOS、DOS、Windows、Linux 或者任何其他软件支持的情况下来显示字符、读取硬盘数据、控制其他硬件等

王爽的《汇编语言》基于 MASM,不少内容也过于陈旧,只能作为参考了

nasm 官网 nasm.us

寄存器

寄存器 宽度 类型
rax 64bit long
eax 32bit int
ax 16bit short
ah 8bit ax 寄存器的高八位
al 8bit al 寄存器的低八位

“X” 表示 Extern,表示从 8 位扩展到 16 位

“E”,还是 Extern 的意思

64 位 , “E” 换成 “R”,如RAX

通用寄存器

数据寄存器 解释 备注
EAX(Accumulator) 累加器 乘除法中被自动使用;Win32 一般用在函数的返回值
EBX(Base) 基址寄存器 DS 段中的数据指针
ECX(Count) 计数器 循环(LOOP)或串操作中,ECX 用来进行循环计数,每执行一次循环,ECX 都会被 CPU 自动减一;c++中保存 this
EDX(Data) 数据寄存器
指针变址寄存器 解释 备注
EBP(Base Pointer) 扩展基址指针寄存器 SS 段中堆栈内数据指针。EBP 由高级语言用来引用参数和局部变量,通常称为堆栈基址指针寄存器
ESP(Stack Pointer) 堆栈指针寄存器 表示栈顶指针, 指向栈顶地址 与 SS 相配合使用
ESI(Source Index) 源变址寄存器 默认段地址和 DI 一样, 在 DS 中和 DS 联用
EDI(Destination Index) 目的指针寄存器 一般情况下与 ds 联用, 来确定某个储存单元的地址

sp 和 bp 段地址默认在 SS 中

sp 指向栈顶元素地址,有自加和自减能力, bp 没, 但可以定位栈中某个元素的物理地址

变址寄存器DI/SI可以和 bx/bp 联用, 和 bx 连用时, 段地址在 DS 中, 和 bp 联用时, 段地址在 SS 中. 也可以单独使用, 单独使用时, 段地址默认在 DS 中, 想要越段使用, 加上段前缀即可

串指令操作中,si 和 ds 联用, 确定目标源地址,di 和 es(附加段寄存器) 联用, 确定传送的目的地址. 说白了就是, 分别寻址数据段和附加段. 在串指令中,si 和 di 具有自加和自减功能

段寄存器

寄存器 解释 备注
CS(Code Segment) 代码段
DS(Data Segment) 数据段
SS(StackSegment) 堆栈段
ES(Extra Segment) 附加数据段
FS 附加数据段
GS 附加数据段

标志寄存器

CPU 根据指令的执行结果,自己操作这个寄存器

nasm伪指令

初始化数据:db 家族

数据类型 大小 伪指令 含义
byte 8 db define byte
word 16 dw define word
dword 32 dd define doubleword
qword 64 dq define quadword
tword 80 dt define tword
oword 128 do define oword
yword 256 dy define yword

非初始化数据:resb 家族

resb 相当于 Microsoft MASM 语法中的 db ?

伪指令 含义
resb reserve byte
resw reserve word
resd reserve doubword
resq reserve quadword
rest reserve tword
reso reserve oword
resy reserve yword

包含 binary 文件

1
2
3
4
incbin  "file.dat"             ; include the whole file
incbin  "file.dat",1024        ; skip the first 1024 bytes
incbin  "file.dat",1024,512    ; skip the first 1024, and
                               ; actually include at most 512

$标号和 times 重复

$ 标号表示 nasm 编译后当前指令位置

$$ 标号表示当前 section 起始位置

1
2
3
times 510-($-$$) db 0
dw 0xaa55
;经常出现在 boot 磁盘 MBR 引导代码中,除了最后 2 个字节和 code 代码外的区域全部写 0 值

hello.asm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
  section .data
msg:
    db "hello, world", 10
len equ $-msg
    section .text
    global main
main:
    mov edx, len
    mov ecx, msg
    mov ebx, 1
    ;直接使用sys_write系统调用
    mov eax, 4  
    int 0x80

    mov ebx, 0
    mov eax, 1
    int 0x80
1
nasm -felf32 hello.asm && ld -melf_i386 -e main -o hello hello.o
series: