寄存器操作数
在本教程中,我们只关心整数寄存器和 xmm 寄存器。您应该已经知道什么是寄存器,但是这里是一个快速的回顾。16 个整数寄存器为 64 位宽,称为:
R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15
RAX RCX RDX RBX RSP RBP RSI RDI
R0 = RAX, R1 = RCX, R2 = RDX, R3 = RBX, R4= RSP, R5 = RBP, R6 = RSI, R7 = RDI
(请注意,其中的最后 8 个寄存器具有备用名称)您可以将每个寄存器的最低 32 位视为寄存器本身,但可以使用以下名称:
R0D R1D R2D R3D R4D R5D R6D R7D R8D R9D R10D R11D R12D R13D R14D R15D
EAX ECX EDX EBX ESP EBP ESI EDI
R0D = EAX, R1D = ECX, R2D = EDX, R3D = EBX, R4D = ESP, R5D = EBP, R6D = ESI, R7D = EDI
您可以使用以下名称将每个寄存器的最低 16 位看作一个寄存器:
R0W R1W R2W R3W R4W R5W R6W R7W R8W R9W R10W R11W R12W R13W R14W R15W
AX CX DX BX SP BP SI DI
R0W = AX, R1W = CX, R2W = DX, R3W = BX, R4W = SP, R5W = BP, R6W = SI, R7W = DI
您可以使用以下名称将每个寄存器的最低 8 位看作一个寄存器:
R0B R1B R2B R3B R4B R5B R6B R7B R8B R9B R10B R11B R12B R13B R14B R15B
AL CL DL BL SPL BPL SIL DIL
由于历史原因,R0...R3
的第 8 至 15 位被命名为:
AH CH DH BH
最后,有 16 个 XMM 寄存器,每个 128 位宽,名为:
XMM0 ... XMM15
研究这张照片;希望它可以帮助:
内存操作数
这些是寻址的基本形式:
[ number ]
[ reg ]
[ reg + reg*scale ]
小数位数只能是 1、2、4 或 8[ reg + number ]
[ reg + reg*scale + number ]
这个数字叫做位移 ; 普通寄存器称为基 ; 带有刻度的寄存器称为索引。
例子:
[750] ; 仅位移
[rbp] ; 仅基址寄存器
[rcx + rsi*4] ; 基数+指数*比例
[rbp + rdx] ; scale is 1
[rbx-8] ; 位移-8
[rax + rdi*8 + 500] ; 所有四个组成部分
[rbx + counter] ; 使用变量"counter"地址作为偏移
直接操作数
这些可以用多种方式编写。以下是官方文档中的一些示例。
200 ; 十进制数
0200 ; 仍然是十进制-前导0不会使其变为八进制
0200d ; 显式十进制-d后缀
0d200 ; 也十进制-0d prefex,推荐
0c8h ; 十六进制-h后缀,但是前导0是必需的,因为c8h看起来像var
0xc8 ; hex-经典的0x前缀,推荐
0hc8 ; 十六进制-由于某些原因,NASM偏爱0h写法,推荐
310q ; 八进制-q后缀
0q310 ; 八进制-0q前缀,推荐
11001000b ; 二进制-b后缀
0b1100_1000 ; 二进制-0b前缀,顺便说一下,允许使用下划线,推荐
具有两个内存操作数的指令非常少见
实际上,在本教程中我们将看不到任何此类说明。大多数基本说明只有以下几种形式:
add reg, reg |
---|
add reg,mem |
add reg, imm |
add mem,reg |
add mem, imm |
定义数据并保留空间
这些示例来自 docs 的第 3 章。要将数据放入内存中:
db 0x55 ; 只是字节0x55
db 0x55,0x56,0x57 ; 连续三个字节
db 'a',0x55 ; 字符常量可以
db 'hello',13,10,'$' ; 字符串常量也是如此
dw 0x1234 ; 0x34 0x12
dw 'a' ; 0x61 0x00(只是一个数字)
dw 'ab' ; 0x61 0x62(字符常量)
dw 'abc' ; 0x61 0x62 0x63 0x00(字符串)
dd 0x12345678 ; 0x78 0x56 0x34 0x12
dd 1.234567e20 ; 浮点常数
dq 0x123456789abcdef0 ; 八字节常量
dq 1.234567e20 ; 双精度浮点
dt 1.234567e20 ; 扩展精度浮点
还有其他形式。请稍候自行查阅 NASM 文档。
要保留空间(无需初始化),可以使用以下伪指令。它们应该放在一个称为.bss
的小节中(如果您试图在一个.text
小节中使用它们,将会出现错误):
buffer: resb 64 ; 保留64个字节
wordvar: resw 1 ; 保留一个字
realarray: resq 10 ; 十个实数的数组
另一个例子
这是一个要研究的 macOS 程序:
triangle.asm
; ----------------------------------------------------------------------------------------
; 这是一个OSX控制台程序,将星号的小三角形写成标准
; 输出。仅在macOS上运行。
;
; nasm -fmacho64 triangle.asm && gcc hola.o && ./a.out
; ----------------------------------------------------------------------------------------
global _main
default rel
section .text
_main:
push rbx ; OSX必须,保存栈,Linux下删除该行
mov rdx, output ; rdx holds address of next byte to write
mov r8, 1 ; initial line length
mov r9, 0 ; number of stars written on line so far
line:
mov byte [rdx], '*' ; write single star
inc rdx ; advance pointer to next cell to write
inc r9 ; "count" number so far on line
cmp r9, r8 ; did we reach the number of stars for this line?
jne line ; not yet, keep writing on this line
lineDone:
mov byte [rdx], 10 ; write a new line char
inc rdx ; and move pointer to where next char goes
inc r8 ; next line will be one char longer
mov r9, 0 ; reset count of stars written on this line
cmp r8, maxlines ; wait, did we already finish the last line?
jng line ; if not, begin writing this line
done:
mov rax, 0x02000004 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, output ; address of string to output
mov rdx, dataSize ; number of bytes
syscall ; invoke operating system to do the write
;exit(0)
pop rbx ; OSX必须,弹出开头保存的栈,Linux下删除该行
;mov rax, 0x02000001 ; system call for exit
;xor rdi, rdi ; exit code 0
;syscall ; invoke operating system to exit
ret
section .bss
maxlines equ 8
dataSize equ 44
output: resb dataSize
$ nasm -fmacho64 triangle.asm && ld triangle.o && ./a.out
*
**
***
****
*****
******
*******
********
此示例中的新内容:
cmp
做比较je
如果先前的比较相等则跳转。jne
(如果不等于则跳转)jl
(如果不等于则跳转)jnl
(如果不小于则跳转)jg
(如果大于则跳转)jng
(如果不大于则跳转)jle
(如果小于或等于则跳转)jnle
(如果不小于或等于则跳转)jge
(如果大于或等于则跳转)jnge
(如果不大于或等于则跳转)equ
实际上不是真正的指令。它只是定义了供汇编程序本身使用的缩写。(这是一个意义深远的想法)- 本
.bss
节适用于可写数据。