博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
计算机组成原理学习笔记——常用X86 汇编指令
阅读量:3935 次
发布时间:2019-05-23

本文共 5283 字,大约阅读时间需要 17 分钟。

X86 汇编指令

1、相关寄存器

  • X86 处理器中有 8 个 32 位的通用寄存器。
    在这里插入图片描述
  • 为了向后兼容,EAX、EBX、ECXEDX高两位字节和低两位字节可以独立使用,E 为 Extended 表示 32 位的寄存器;例如 EAX 的低两位字节称为 AX,而 AX 的高低字节又可分别作为两个 8 位寄存器,分别称 AH 和 AL。寄存器的名称大小写都可以。除 EBP 和 ESP 外,其他几个寄存器的用途是比较任意的

2、寻址模式和内存分配

1)寻址模式

  • X86 提供了一种灵活的内存寻址方式,以 mov 为例,mov 用于在内存和寄存器之间移动数据,它有两个参数:第一个是目的地地址,第二个是源地址,示例如下:
mov eax, [ebx]                ;将 ebx 值指示的内存地址中的 4 字节传送到 eax	mov [var], ebx                 ;将 ebx 值传送到 var 的值指示的内存地址中	mov eax, [esi-4]              ;将 esi-4 值指示的内存地址中的 4 字节传送到 eax	mov [esi+eax], cl;	mov edx, [esi+4*ebx];

注意:最多只能利用两个 32 位寄存器和一个 32 位的有符号常数相加计算出一个内存地址

2)数据类型长度规定

  • 汇编语言中声明内存大小时,一般显式的使用 DB(D 表示 Data,B 表示 Byte)、DW(W 表示 Word,2Bytes)和DD(第二个字母 D 表示 Double World,4Bytes),这样就能指导编译器分配内存空间,但是对于:
mov [ebx], 2;
  • 若无特殊标记,则不确定常数 2 是单字节、双字节还是双字,为此,X86 提供了三个指示规则标记:BYTE PTR, WORD PTR 和 DWORD PTR,则上述例子可写成:
mov byte ptr [ebx], 2;      将 2 以单字节形式传输到 ebx 值指示的内存地址中	mov word ptr [ebx], 2;    将 2 以双字节的形式传送到 ebx 值指示的内存地址中	mov dword ptr [ebx], 2;  将 2 以四字节的形式传送到 ebx 值指示的内存地址中

3、常用指令

  • 汇编指令通常可以分为数据传送指令、逻辑计算指令和控制流指令
    以下用于操作数的标记分别表示寄存器、内存和常数:
:表示任意寄存器,若其后带有数字,则指定其位数,如
表示 32 位寄存器(EAX,EBX,ECX,EDX,ESI,EDI,ESP 或 EBP);
表示 16 位寄存器(AX, BX, CX 或 DX);
表示 8 位寄存器(AH、AL、BH、BL、CH、CL、DH、DL)。
:表示内存地址
:表示 8 位、16 位或 32 位常数,
表示 8 位常数。
  • X86 中的指令机器码长度位 1 字节,对同一指令的不同用途有多种编码方式,比如 mov 指令就有 28 种机内编码,用于不同操作数类型或用于特定寄存器,例如:
mov ax, 
; 机器码为 B8H mov al,
; 机器码为 B0H mov
/
,
; 机器码为 89H mov
,
/
; 机器码为 8AH mov
,
/
; 机器码为 8BH

1)数据传送指令

mov 指令
  • mov 指令将第二个操作数——寄存器的内容、内存中的内容或常数值,复制到第一个操作数——寄存器或内存,但不能用于直接从内存复制到内存,语法如下:
mov 
,
mov
,
mov
,
mov
,
mov
,
example: mov eax, ebx; mov byte ptr [var], 5;
push 指令
  • push 指令将操作数压入内存的栈,常用于函数调用。ESP 是栈顶,压栈前先将 ESP 值减 4,因为栈增长方向与内存地址增长方向相反,然后将操作数压入 ESP 指示的地址;栈中元素固定为 32 位。语法:
push 
push
push
example: push eax; push [var]; 将 var 指示的内存地址的 4 字节值压入栈
pop 指令
  • pop 指令执行出栈工作,出栈前先将 ESP 指示的地址种内容取出栈,然后将 ESP 值加 4,语法如下:
pop edi;    弹出栈顶元素送到 edi	pop [ebx];   弹出栈顶元素送到 ebx 值指示的内存地址的 4 字节中

2)算术和逻辑运算指令

add/sub 指令
  • add 指令将两个操作数相加,相加的结果保存到第一个操作数中。sub 指令用于两个操作数相减,相减的结果保存到第一个操作数中,语法格式入下:
add 
,
add
,
add
,
add
,
add
,
sub
,
sub
,
sub
,
sub
,
sub
,
example: sub eax, 10 ;eax ←eax-10 add byte ptr [var], 10 ;10 与 var 值指示的内存地址的一字节值相加,并将结果保存在与 var 值指示的内存地址的字节中
inc/dec 指令

inc、dec 指令分别表示操作数自加 1、自减 1,其语法格式如下:

inc 
inc
dec
dec
example: dec eax ;eax 值自减 1 inc dword ptr [var] ;var 值指示的内存地址的 4 字节值自加 1
imul 指令
  • 带符号整数乘法指令,有两种格式:1)两个操作数,将两个操作数相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器;2)三个操作数,将第二个和第三个操作数相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器;语法格式如下:
imul 
,
imul
,
imul
,
,
imul
,
,
example: imul eax, [var] ;eax←eax * [var] imul esi, edi, 25 ; esi←edi * 25
  • 乘法结果可能溢出,则编译器溢出标志 OF =1,以使 CPU 调出溢出异常处理程序。
idiv 指令
  • 带符号整数除法指令,只有一个操作数,即除数,而被除数则为 edx:eax 中的内容,64 位整数;操作结果分为两部分:商和余数,商送到 eax,余数送到 edx;语法格式如下:
idiv 
idiv
example: idiv ebx idiv dword ptr [var]
and/or/xor 指令
  • 逻辑与、逻辑或、逻辑异或操作指令,用于操作数的位操作,操作结果放在第一个操作数中;语法格式如下,由于格式类似,只需将前面的指令改一下就可以,所以这里以 and 为例:
and 
,
and
,
and
,
and
,
example: and eax, ofH ;将 eax 中的前28 位全部置零,最后 4 位不变 xor edx, edx ;置 edx 中的内容为
not 指令
  • 位翻转指令,将操作数的每一位翻转,即0⟶1,1⟶0;语法格式如下:
not 
not
example: not byte ptr [var] ;将 var 值指示的内存地址的一字节的所有位翻转。
neg 指令
  • 取负指令,语法格式如下:
neg 
neg
example: neg eax
shl/shr 指令
  • 逻辑位移指令,shr 为逻辑右移,shl 表示逻辑左移,第一个操作数表示被操作数,第二个操作数指示移位的位数;语法格式如下:
shl 
,
shl
,
shl
,
shl
,
; 上面的 shl 改成 shr 就是逻辑右移的格式 example shl eax, 1 ;将 eax 的值左移 1 位,相当乘于 2 shr ebx, cl ;将 ebx 值右移 n 位,n 为 cl 中的值,相当于除于 2^n

3)控制流指令

  • X86 处理器维持这一个指示当前执行指令的指令指针(IP),当执行一条指令后,此指针自动指向下一条指令。IP 寄存器不能直接操作,但可以用控制流指令更新。通常用标签(label)指示程序中的指令地址,在 X86 汇编代码中,可在任何指令前加入标签,例如:
mov esi, [edp+8]	begin:         xor ecx, ecx			mov eax, [esi]
  • 这样就用 begin 指示了第二条指令,控制流指令通过标签可以实现程序的跳转。
jmp 指令
  • 控制 IP 转移到 label 所指示的地址,从 label 中取出指令执行;语法格式如下:
jmp 
jcondition 指令
  • 条件转移指令,它依据处理机状态字中的一系列条件状态转移。处理机状态字包括指示最后一个算术运算结果是否为 0,运算结果是否为负数等;语法格式如下:
je 
cmp 指令
  • 比较两个操作数的值,并根据比较结果设置处理机状态字中的条件码;语法格式如下:
cmp 
,
cmp
,
cmp
,
cmp
,
  • 通常与 jcondition 指令搭配使用:
cmp dword ptr [var], 10	jne loop   ;如果 var 指示的内存地址的 4 字节内容等于 10,则继续执行下一条指令;否则跳转到 loop 指示的指令执行。
call/ret 指令
  • 这两条指令实现子程序(过程、函数等)的调用及返回。call 指令首先将当前指令地址入栈,然后无条件转移到由标签指示的指令。与其他简单的跳转指令不同,call 指令保存调用之前的地址信息,当 call 指令结束后,返回调用之前的地址。ret 指令实现子程序的返回机制,ret 指令弹出栈中保存的指令地址,然后无条件转移到保存的指令地址执行。call 和 ret 是函数调用中最关键的两条指令,其语法格式如下:
call 

转载地址:http://ymqgn.baihongyu.com/

你可能感兴趣的文章
工作日志
查看>>
https工作原理
查看>>
php文件操作
查看>>
php 判断字符串类型及长度
查看>>
php设计模式
查看>>
php与java通信
查看>>
socket
查看>>
TCP HTTP UDP 区别
查看>>
PHP单例模式
查看>>
PHP项目设计
查看>>
memcache的安装及管理
查看>>
递归列出所有目录和文件
查看>>
PHP发送邮箱类及应用
查看>>
PHP操作文件夹
查看>>
php 获取客户端所在城市地址
查看>>
ruby脚手架
查看>>
rubyonrails安装
查看>>
ruby 中 include 与 extend 区别
查看>>
几种常见Ruby on Rails内置方法介绍
查看>>
页面跳转实现方法总结
查看>>