NASM入门第二发-~~~~~~~~~
---------------------------Basic Instruction Set[基础指令集]
这一节,我们将会讨论NASM基本指令集的语法、语义,看到一些例子。
1.MOV-Move/Copy
将一个寄存器或者内存单元里面的内容拷贝到另一个寄存器或者内存单元中,或者将内存单元中的值、寄存器中的变量赋值为立即数。
sy:
mov dest, src
~~src是源操作数,应该是一个寄存器或者内存操作数
~~源操作数和目的操作数不能同时是取自内存的操作数
2.MOVZX-Move and Extend
拷贝并扩展一个lower spaced(提供较低地址空间--位数少的)内存/寄存器的值到一个可以提供较大地址空间的内存/寄存器单元
sy:
mov zx src, dec
~~目的操作数的位数>=源操作数的位数
~~src应该是一个寄存器/内存操作数
~~源操作数和目的操作数不能同时是取自内存的操作数
~~只能用户无符号数
Eg:
movzx eax,ah
movzx cx , al
--为扩展有符号数,我们使用向CBW(convert byte to word)、CWD(convert word to double)这样的指令
--CBW扩展AL寄存器至AX
--CWD扩展AX到DX:AX寄存器对
3.ADD--Addition
sy:
add dest, src
dest=dest+src
用于计算两个寄存器/内存变量的和,将结果存进源操作数的位置。
~~源操作数应该是一个寄存器/内存操作数
~~源操作数和目的操作数不能同时是取自内存的操作数
~~源操作数和目的操作数的位数应该是一致的
Eg:
add eax, ecx ; eax=eax+ecx;
add al, ah ; al=al+ah
add ax, 5 ;ax=ax+5
add edx, 31h
4.SUB--Subtraction
sy:
sub dest, src
dest=dest-src;
用于计算两个寄存器/内存变量的差,将结果存进源操作数的位置。
~~源操作数应该是一个寄存器/内存操作数
~~源操作数和目的操作数不能同时是取自内存的操作数
~~源操作数和目的操作数的位数应该是一致的
Eg:
sub eax, ecx ; eax=eax-ecx
sub al, ah;
sub ax, 5
sub edx, 31h
5.INC--Increment Operation
用于将一个寄存器/内存变量增量1,类似于高级语言中的++
Eg:
INC eax, eax++
INC byte[var]
INC a1
6.DEC--Decrement Operation
用于将一个寄存器/内存变量减少一
Eg:
DEC eax; eax--
DEC byte[var]
DEC al
7,MUL--Multiplication
Sy:
mul src
用于将一个寄存器/内存变量和EAX/AX/AL寄存器相乘。MUL依据以下规则进行运算
~~如果src是1Byte,那么AX=AL*src
~~如果src是一个字长(16Byte),那么DX:AX=AX*src(结果的高16位将会进入DX,低16位将会进入AX)
~~如果Src是两个字长的(32Byte),那么EDX:EAX=EAX*src(结果的高32位将会进入EDX,低32位进入EAX)
8.IMUL--Multiplication of signed numbers
IMUL指令用于有符号数的相乘,主要有以下三种不同的用法:
Sy:
(i) imul src
(ii) imul dest, src
(iii) imul dest, src1, src2
~~如果按照(i)中的方法使用,其语义和MUL一致
~~如果按照(ii)中的方法使用,dest=dest*src
~~如果按照(iii)中的方法使用,dest=src1*src2
9.DIV--Division
Sy:
div src
用于将EAX/AX/AL寄存器和一个寄存器/内存变量相除。DIV依据以下规则进行运算
~~如果src是一个字长(16Byte),AX将会被src除,余数将会进入AH,商数进入AL
~~如果src是一个字长(16Byte),那么DX:AX将会被src除,余数进入DX,商数进入AX
~~如果Src是两个字长的(32Byte),那么EDX:EAX将会被src除,余数进入EDX,商数进入EAX
10.NEG--Negation of signed numbers
Sy:
NEG opl
NEG 指令将给出的寄存器/内存变量取反
11.CLC--Clear Carry
此指令用于将CPU FLAGS中的进位标志位[carry flag]清空为0
12.ADC--Add with Carry
Sy:
ADC dest, src
ADC用于较大数字的相加。假如我们想将两个64bit的数字相加,我们将第一个数字放在EDX:EAX(将最有意义起决定性作用的32bits放在EDX中,其他在EAX中),将第二个数字放在EBX:ECX中,而后像如下这样做加法。
Eg:
clc ; 清空进位
add eax, ecx ; eax和ecx之间正常的加法
adc edx, ebx;对于高位使用带进位加
13.SBB--Subtract with Borrow
Sy:
SBB dest, src
SBB和ADC是相似的。
NASM中的分支指令:
14.JMP--Uncoditionally Jump to label
JMP 与C/C++中的goto比较相似,用于实现将控制流跳转到程序中的任意地方而不做任何条件判断
Eg:
label: _______________
_______________
JMP label
_______________
_______________
JMP exit
_______________
_______________
exit:
15:CMP--Compares the Operands
Sy:
CMP op1, op2
当对两个操作数op1,op2使用CMP时候,将会执行op1-op2,但不会存储结果,反之,他将会影响CPU FLAGS。这就像是不存储结果的减法指令一样。比如若是op1==op2,那么ZERO FLAGS(ZF)将会被置为1,。
NB:对于nasm中的条件跳转,首先用CMP指令将ZF置位,然后用以下指令实现对ZF的检查和跳转
Condition Jump Instructions:
Eg: 将if 语句转化为nasm 代码
if(cax>=ebx)
eax++;
else
ebx++;
/*转化后的代码*/
cmp eax, ebx
JNC if
INC ebx ;ELSE part
JMP L1
if: ;If Part
INC eax
L1:
........
Advanced conditional Jump Instructions[高级条件跳转指令]:
Eg:
CMP ax, bx ;比较
JA L1 ;跳转
INC ax ;Else Part
JMP L2
L1: ;If Part
INC bx
L2:
......
16,Loop Instruction循环指令
Sy:
loop label
当我们使用loop指令的时候,ecx用做循环计数器,Loop指令开始时自减ecx的值,而后检查ecx的新值,是不是ecx!=0的情形,如果是的话,那么将跳转至label所标记的位置,否则控制流将会跳向下一条指令。
Eg:
mov ecx, 10
mov eax, 0
add:
add eax, ecx
loop add
Converting Standard C/C++ Control Structures to NASM:
//**************** (i) ******************
//if-else
if(eax>5)
eax=eax+ebx;
else
ecx=ecx+ebx;
//nasm statement
CMP eax,5;
JA IF
ELSE:
ADD ecx,ebx
JMP L2
IF:
add eax,ebx
L2:
//**************** (i) ******************
//**************** (ii) ******************
//For loop
eax=0;
for(ebx=1 to 10)
eax=eax+ebx;
//nasm statement
MOV eax,0
MOV ebx,1
FOR:
ADD eax,ebx
CMP ebx,10
JBE FOR
//**************** (ii) ******************
//**************** (iii) ******************
//While-loop
sum=0;
ecx=n;
while(ecx>0)
sum=sum+ecx;
//nasm statement
MOV dword[sum],0
MOV ecx, dword[n]
ADD:
ADD [sum],ecx
loop ADD
//**************** (iii) ******************
Boolean Operations:
17.AND--bitwise Logical AND
sy:
AND op1, op2
执行按位与操作,结果被放入op1的位置。
18.OR--bitwise logical OR
sy:
OR op1, op2
执行按位或操作,结果被存入op2的位置
19.XOR--bitwise Logical Exclusive OR
Sy:
XOR op1,op2
执行按位异或,结果存入op1的位置
20.NOT--Bitwise Logical Negation
sy:
NOT op1
按位取反,结果进入Op1
21.TEST--Logical AND, affects only CPU FLAGS
sy: TEST op1
~~和CMP的用法类似,按位与运算的结果不会被保存,而是依据结果对CPU FLAGS进行置位。
22.SHL--shift Left
sy:
SHL op1,op2
op1=op1<<op2;//等价的C语句
~~执行按位左移,op1是寄存器/内存变量,op2 必须是立即数,或者是常量值
~~将会把op1左移op2位,末位补0
23.SHR--shift right
sy:
SHR op1,op2
op1=op1>>op2;//等价的C语句
~~执行按位右移,op1是寄存器/内存变量,op2必须是立即数或者常量
~~op1左移op2位,高位补0
24.ROL--Rotate Left
sy:
ROL op1,op2
~~ROL执行按位的循环左移,op1是寄存器/内存变量,op2是立即数。
Eg:
rol eax,5
25.ROR --Rotate right
sy:
ROR op1,op2
~~ROR执行按位的循环右移,op1是寄存器/内存变量,op2是立即数。
26.RCL--Rotate Left with Carry
sy:
RCL op1,op2
27.RCR--Rotate Right with Carry
sy:
RCR op1,op2
Stack Operations:
28.PUSH--Pushes a value into system stack
减少ESP的值,将寄存器或者是常量的值压入系统栈
Eg:
PUSH ax; ESP=ESP-2 and copies value of ax to [EBP]
PUSH eax; ESP=ESP-4 and copies value of ax to [EBP]
PUSH ebx;
PUSH dword 5
PUSH word 256
29.POP--pop off a value from the system stack
将栈顶的值存至寄存器,并且增加ESP的值
Eg:
POP bx; ESP=ESP+2;
POP ebx; ESP=ESP+4;
POP eax
这篇就到这里~~Thx!