FASM 第二章 - 2.1 x86 体系指令
Author: 徐艺波 From: xuyibo.org Updated: 2008-04-17官方论坛
本站软件反馈、软件开发交流。 邮件通知
当更新时自动发送邮件通知。 评论本文
有什么建议或评论,可以贴一下。 捐助
你的支持,让我们做的更好。 -
2.1 x86 体系指令
-
2.1.1 数据传送指令
2.1.2 类型转换指令
2.1.3 二进制算术指令
2.1.4 十进制算术指令
2.1.5 逻辑指令
2.1.6 控制转移指令
2.1.7 I/O 指令
2.1.8 字符串操作指令
2.1.9 标志控制指令
2.1.10 条件操作指令
2.1.11 其他指令
2.1.12 系统指令
2.1.13 FPU 指令
2.1.14 MMX 指令
2.1.15 SSE 指令
2.1.16 SSE2 指令
2.1.17 SSE3 指令
2.1.18 AMD 3DNOW!指令
2.1.19 x86-64长模式指令
2.1 x86 体系指令
这一章讲述了汇编语言指令语法和功能。更多的技术信息可以阅读Intel软件开发者手册。
汇编指令有助记符(指令名称)和0到3个操作符组成。如果有大于两个的操作符,通常第一个为目的操作符第二个为源操作符。每个操作符都可以为寄存器,内存或立即数(操作符语法见1.2节)。每条指令描述后悔有操作符不同用法的例子。
一些指令用作前缀,可以和其他指令放在同行一起使用,一行也允许有多个前缀。段寄存器也是指令助记符前缀,但推荐在方括号中段重写来替代这些前缀。
2.1.1 数据传送指令
mov从源操作符传送字节,字或双字道目的操作符。它可以在通用寄存器之间,通用寄存器到内存,或从内存到通用寄存器间传送数据,但不能在内存间传送数据。它也可以在立即数到通用寄存器或内存,段寄存器到通用寄存器或内存,通用寄存器或内存到段寄存器,控制或调试寄存器到通用寄存器以及通用寄存器到控制或调试寄存器间传送数据。只有当源操作符和目的操作符大小相同时mov才能被汇编。下面是一些例子:mov bx,ax ; 通用寄存器到通用寄存器 mov [char],al ; 通用寄存器到内存 mov bl,[char] ; 内存到通用寄存器 mov dl,32 ; 立即数到通用寄存器 mov [char],32 ; 立即数到内存 mov ax,ds ; 段寄存器到通用寄存器 mov [bx],ds ; 段寄存器到内存 mov ds,ax ; 通用寄存器到段寄存器 mov ds,[bx] ; 内存到段寄存器 mov eax,cr0 ; 控制寄存器到通用寄存器 mov cr3,ebx ; 通用寄存器到控制寄存器
xchg置换两个操作数内容。它可以用来置换两个字节、字或者双字操作数。操作数的顺序并不重要。操作数可以为两个通用寄存器,或者通用寄存器同内存。例如:
xchg ax,bx ; 置换两个通用寄存器 xchg al,[char] ; 寄存器和内存置换
push递减堆栈指针(esp寄存器),然后传送操作数到esp执行的栈顶。操作数可以为内存,通用寄存器,段寄存器或字、双字立即数。如果操作数为没有指定大小的立即数时,汇编器在16位模式下默认将当作16位值,在32位模式下将当作32位值。pushw和pushd助记符为push指令的变种,分别用来压入16位,32位大小值到堆栈。如果同行后指定了更多参数(空格分隔,而非逗号),将汇编为一串push指令。下面为带有单一操作符的例子:
push ax ; 压入通用寄存器到堆栈 push es ; 压入段寄存器 pushw [bx] ; 压入内存值 push 1000h ; 压入立即数
pusha压入8个通用寄存器的内容到堆栈,这条指令没有操作数。这条指令有两个版本,一个16位的和一个32位的,汇编器自动根据当前模式生成正确的版本,但也可以使用pushaw或pushad助记符重写为只为16位或32位版本。16位版本的这条指令将以以下顺序压入通用寄存器:ax,cx,dx,bx,压入ax前的sp值,bp,si和di。32为版本将以相同顺序压入等价的32位通用寄存器。
pop传送当前栈顶的字或双字到目的操作符,然后递增esp指向新的栈顶。操作符可以为内存,通用寄存器或段寄存器。popw和popd助记符为pop指令的变种,分别用来弹出字或双字。如果同行后指定了更多参数(空格分隔,而非逗号)将汇编为一串pop指令。
pop bx ; 弹出栈顶数据到通用寄存器 pop ds ; 弹出到段寄存器 popw [si] ; 弹出到内存
popa弹出堆栈中由pusha指令压入的寄存器,将忽略其中保存的sp(或esp)值。使用popaw或popad助记符来强制汇编16位或32位版本的这条指令。
2.1.2 类型转换指令
类型转换指令转换字节为字,字为双字,双字为四字。这些转换可以为符号扩展或零扩展的。符号扩展将用符号位来填充,而零扩展将使用0来填充。
cwd和cdq分别用来扩展ax和eax大小,并将额外位存储到dx和edx中。转换将使用符号扩展。这些指令没有操作数。
cbw符号扩展al的值到ax,cwde符号扩展ax到eax。这些指令也没有操作数。
movsx使用符号扩展将字节转换为字或双字,字转换为双字。movzx类似,只是它使用0扩展。源操作数可以为通用寄存器或内存,目的操作数必须为通用寄存器。例如:
movsx ax,al ; 字节寄存器转换为字寄存器 movsx edx,dl ; 字节寄存器转换为双字寄存器 movsx eax,ax ; 字寄存器转换为双字寄存器 movsx ax,byte [bx] ; 字节内存之后为字寄存器 movsx edx,byte [bx] ; 字节内存转换为双字寄存器 movsx eax,word [bx] ; 字内存转换为双字寄存器
2.1.3 二进制算术指令
add替换目的操作数的值为源操作数和目的操作数的和,并且在溢出时设置CF标志。操作数可以为字节,字或双字。目的操作数可以为通用寄存器或内存,源操作数可以为通用寄存器或立即数,如果目的操作数为寄存器也可以为内存。
add ax,bx ; add 寄存器到寄存器 add ax,[si] ; add 内存到寄存器 add [di],al ; add 寄存器到内存 add al,48 ; add 立即数到寄存器 add [char],48 ; add 立即数到内存
adc和add类似,只是如果设置CF的话结果还将递增1。add后跟着多个adc指令能用来计算大于32位值的和。
inc将操作数值递增1,它不影响CF。操作数可以为通用寄存器或内存,操作数大小可以为字节,字或双字。
inc ax ; 寄存器值递增1 inc byte [bx] ; 内存值递增1
sub用目的操作数值减去源操作数,并且用结果替换目的操作数。如果需要借位,将设置CF。操作数规则和add指令相同。
sbb和sub类似,只是如果设置CF的话结构还将递减1。操作数规则和add质量相同。sub后跟着多个sbb指令能用来计算大于32位值的差。
dec将操作数值递减1,它不影响CF。操作数规则和inc指令相同。
cmp用目的操作数减去源操作数,类似sub指令更新标志值,但它不改变源和目的操作符。操作数规则和sub指令相同。
neg用0减去带符号的整数操作数。这条指令的效果是将带符号的操作数从正数变为负数或者从负数变为正数。操作数规则和inc指令相同。
xadd交换目的和源操作数,然后载入两个值的和到目的操作数。操作数规则和add指令相同。
所有上面的二进制算术指令都将更新SF,ZF,PF和OF标志。SF被设置为结果符号位的值,ZF当结果为0时设置为1,PF当低8位存在偶数个1时设置,OF在结果对于正数太大或对于负数太小(超过符号位)以放到目的操作数中时设置。
mul计算无符号操作数和累加器的积。如果为8位操作数,将和al计算积,16位结果返回到ah和al中。如果4,为16位操作数,将和ax计算积,32位结果返回到dx和ax中。如果为32位操作数,将和eax计算积,64位结果返回到edx和eax中。当结果高半部分不为零时将设置标志CF和OF,否则将清除该标志。操作数规则和inc指令相同。
imul执行符号乘法运算。这条指令有3种用法。第一种允许一个操作数,和mul指令类似。第二种有两个操作数,此时将计算目的操作数和源操作数的积,并将结果替换目的操作数。目的操作数可以为16位或32位通用寄存器,源操作数可以为通用寄存器,内存或立即数。第三种有3个操作数,目的操作数必须为16位或32位通用寄存器,源操作数可以为通用寄存器或内存,第三种操作数必须为立即数。源操作数乘以立即数并将结果保存到目的寄存器。所有上面三种形式都将计算出双倍大小的结构,并当结果高半部分不为零时设置标志CF和OF。所以第二种和第三种形式也能用作无符号操作数,因为,无论操作数是否为有符号无符号,结果的低半部分是相同的。下面的所有三种形式的乘法指令使用例子:
imul bl ; 累加器和寄存器 imul word [si] ; 累加器和内存 imul bx,cx ; 寄存器和寄存器 imul bx,[si] ; 寄存器和内存 imul bx,10 ; 寄存器和立即数 imul ax,bx,10 ; 寄存器,立即数,值到寄存器 imul ax,[si],10 ; 内存,立即数,值到寄存器
div计算操作数和累加器无符号运算的商。被除数(累加器)为两倍大小的除数(操作数),商和余数和除数有相同尺寸。如果除数为8位,被除数为ax,商和余数分别保存到al和ah中。如果除数为16位,被除数的商的高半部分从dx获取,低半部分从ax获取,商和余数分别保存到ax和dx中。如果除数为32位,被除数的高半部分从edx获取,低半部分从eax获取,商和余数分别保存到eax和edx中。操作数规则和mul指令相同。
idiv计算操作数和累加器有符号运算的商。它使用和div指令相同的寄存器,操作数的规则也是一样的。
2.1.4 十进制算术指令
十进制算术指令用来调整上一节的二进制算术操作以生成有效的压缩或未压缩十进制结果,或调整输入为一个二进制算术操作序列以使该操作能生产一个有效的压缩或解压缩十进制结果。
daa调整al中两个有效压缩十进制操作数和的值。daa必须跟着两对压缩十进制数(每半字节一个点)的和来得到一对有效压缩十进制数字结果。如果需要进位将设置CF标志。这条指令没有操作数。
das调整al中两个有效压缩十进制操作数差的值。das必须跟着两对压缩十进制数(每半个字节一个点)的差来得到一对有效压缩十进制数字结果。如果如要进位将设置CF标志。这条指令没有操作数。
aaa修改al中的内容为有效的未压缩十进制数字,并将高四位清零。aaa必须跟着al中两个有效未压缩十进制操作数和。如果需要进位将设置CF标志并递增ah的值。这条指令没有操作数。
aas修改al的值为一个有效的未压缩十进制数据,并将
-
2.1.1 数据传送指令
x86 体系指令
最新推荐文章于 2024-05-12 10:46:42 发布