NASM常用指令
mov
mov destination, source
移动数据到寄存器或者内存
移动ebx数据到eax
mov eax, ebx
移动 ebx+8 内存地址的4个字节数据到 eax
mov eax, [ebx+8]
movsx - 符号扩展移动,2个操作数大小不一样,比如16位移动到32位,32位要跟16位同符号
movzx - 0扩展移动,2个操作数大小不一样,比如16位移动到32位,32位的高16位填充0
lea(load effective address)
lea des, src
加载有效地址,假设 ebx = 0x00403A40,那么下面操作后,eax = 0x00403A48
lea eax, [ebx+8]
inc
inc destination
操作数增加1
dec
dec destination
操作数减1
add/sub
add/sub destination, source
Register to register
Memory to register
Register to memory
Register to constant data
Memory to constant data
加减指令,不允许 内存到内存 操作
adc
带进位加法,相当于 add x, x, CF,正常加法再加上进位标志位
mov dl, 0
mov al, ffh
add al, ffh
adc dl, 0 ;dl = 1, al = ffh, dlal = 01ffh
sbb
带进位减法,相当于多减去一个进位标志位的值
mul/imul
MUL/IMUL multiplier
mul为无符号乘,imul为有符号乘,被乘数(multiplicand)存放在 AL 或者 AX里,64位系统有4种情形
;8位乘法,溢出的位存放在 AH, AL为低8位,下面同理
AL * 8bit = AH AL
;下面分别为16 32 64位乘法
AX * 16bit = DX AX
EAX * 32bit = EDX EAX
RAX * 64bit = RDX RAX
div/idiv
DIV/IDIV divisor
div为无符号乘,idiv为有符号乘,商(quotient)存放在 AX,余数(remainder)存放在 DX
AX/8bit = AL AH
DX AX/16bit = AX DX
EDX EAX/32bit = EAX EDX
RDX RAX/64bit = RAX RDX
cmp
比较两个数
CMP destination, source
jmp
JMP label
JMP label
无条件跳转
有条件跳转
下面是有符号
JE/JZ Jump Equal or Jump Zero ZF
JNE/JNZ Jump not Equal or Jump Not Zero ZF
JG/JNLE Jump Greater or Jump Not Less/Equal OF, SF, ZF
JGE/JNL Jump Greater/Equal or Jump Not Less OF, SF
JL/JNGE Jump Less or Jump Not Greater/Equal OF, SF
JLE/JNG Jump Less/Equal or Jump Not Greater OF, SF, ZF
下面是无符号
JE/JZ Jump Equal or Jump Zero ZF
JNE/JNZ Jump not Equal or Jump Not Zero ZF
JA/JNBE Jump Above or Jump Not Below/Equal CF, ZF
JAE/JNB Jump Above/Equal or Jump Not Below CF
JB/JNAE Jump Below or Jump Not Above/Equal CF
JBE/JNA Jump Below/Equal or Jump Not Above AF, CF
其他特殊跳转指令
JE/JZ Jump Equal or Jump Zero ZF
JNE/JNZ Jump not Equal or Jump Not Zero ZF
JA/JNBE Jump Above or Jump Not Below/Equal CF, ZF
JAE/JNB Jump Above/Equal or Jump Not Below CF
JB/JNAE Jump Below or Jump Not Above/Equal CF
JBE/JNA Jump Below/Equal or Jump Not Above AF, CF
loop
loop label
循环指令,需要借助 ecx 寄存器,每次循环 ecx 减去1,当 ecx为0时跳出
逻辑指令
AND AND operand1, operand2
OR OR operand1, operand2
XOR XOR operand1, operand2
TEST TEST operand1, operand2
NOT NOT operand1
test指令跟and一样,只不过不改变源操作数
移位指令
shl 左移
shr 右移
sal 有符号左移
sar 有符号右移
rol 循环左移
ror 循环右移
rcl 带进位的循环左移
rcr 带进位的循环右移
shld 双精度左移
shrd 双精度右移
循环左移,左边移出的那一位将放在低位,循环右移右边移出的那一位放入高位
movsb/movsw/movsd/movsq
单位分别为1,2,4,8字节
移动 DS:RSI 数据到 ES:EDI,方向标志位0 ESI EDI每次增加,方向标志位 1,ESI EDI 每次减少
cld/std
cld 方向标志位置0,即DF=0,std 方向标志为置1,即DF=1
rep
rep - ECX > 0时重复
repz repe - ECX > 0 且 ZF == 1 时重复
repnz repne - ECX > 0 且 ZF == 0 时重复
每次重复,ecx都会减1
下面是复制10个字节的模拟
cld
mov esi,OFFSET string1
mov edi, OFFSET string2
mov ecx,10
rep movsb
call
call function_name
调用函数,主要做了如下2件事
1.将调用函数后需要执行的指令地址压入栈,即call后面的指令地址
2.改变 RIP 指向调用目标地址
ret
弹出返回地址,把控制权交还给调用者
push/pop
进栈出栈,RBP 为指向栈底的指针
cmpsb/cmpsw/cmpsd/cmpsq
比较 ESI 指向的内存操作数与 EDI指向的内存操作数,也可以使用重复前缀 rep
scasb/scasw/scasd/scasq
分别将 AL/AX/EAX/RAX中的值与 EDI 指向的 1,2,4,8字节进行比较,可以结合 repe使用
stosb/stosw/stosd/stosq
分别将AL/AX/EAX/RAX内容存入 EDI 中偏移量指向的内存,EDI 根据方向标志位递增或者递减
lodsb/lodsw/lodsd/lodsq
分别从 ESI 指向的内存地址加载1,2,4,8字节到 AL/AX/EAX/RAX,ESI 根据方向标志位递增或者递减
转载来源
http://www.daileinote.com/computer/assembly/06