<转>汇编指令

本文详细介绍了GAS汇编语言中的操作数格式、数据传送指令、算数和逻辑操作指令等内容。通过具体实例展示了不同指令的应用场景,帮助读者更好地理解和掌握GAS汇编语言。

GAS中每个操作都是有一个字符的后缀,表明操作数的大小。

C声明

GAS后缀

大小(字节)

char

b

1

short

w

2

(unsigned) int / long / char*

l

4

float

s

4

double

l

8

long double

t

10/12

注意:GAL使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。

 

 

操作数格式:

格式

操作数值

名称

样例(GAS = C语言)

$Imm

Imm

立即数寻址

$1 = 1

Ea

R[Ea]

寄存器寻址

%eax = eax

Imm

M[Imm]

绝对寻址

0x104 = *0x104

(Ea)

M[R[Ea]]

间接寻址

(%eax)= *eax

Imm(Ea)

M[Imm+R[Ea]]

(基址+偏移量)寻址

4(%eax) = *(4+eax)

(Ea,Eb)

M[R[Ea]+R[Eb]]

变址

(%eax,%ebx) = *(eax+ebx)

Imm(Ea,Eb)

M[Imm+R[Ea]+R[Eb]]

寻址

9(%eax,%ebx)= *(9+eax+ebx)

(,Ea,s)

M[R[Ea]*s]

伸缩化变址寻址

(,%eax,4)= *(eax*4)

Imm(,Ea,s)

M[Imm+R[Ea]*s]

伸缩化变址寻址

0xfc(,%eax,4)= *(0xfc+eax*4)

(Ea,Eb,s)

M(R[Ea]+R[Eb]*s)

伸缩化变址寻址

(%eax,%ebx,4) = *(eax+ebx*4)

Imm(Ea,Eb,s)

M(Imm+R[Ea]+R[Eb]*s)

伸缩化变址寻址

8(%eax,%ebx,4) = *(8+eax+ebx*4)

注:M[xx]表示在存储器中xx地址的值,R[xx]表示寄存器xx的值,这种表示方法将寄存器、内存都看出一个大数组的形式。

 

 

数据传送指令:

指令

效果

描述

movl S,D

D <-- S

传双字

movw S,D

D <-- S

传字

movb S,D

D <-- S

传字节

movsbl S,D

D <-- 符号扩展S

符号位填充(字节->双字)

movzbl S,D

D <-- 零扩展S

零填充(字节->双字)

pushl S

R[%esp] <-- R[%esp] – 4;

M[R[%esp]] <-- S

压栈

popl D

D <-- M[R[%esp]];

R[%esp] <-- R[%esp] + 4;

出栈

注:均假设栈往低地址扩展。

 

 

算数和逻辑操作地址:

指令

效果

描述

leal S,D

D = &S

movl地版,S地址入D,D仅能是寄存器

incl D

D++

加1

decl D

D--

减1

negl D

D = -D

取负

notl D

D = ~D

取反

addl S,D

D = D + S

subl S,D

D = D – S

imull S,D

D = D*S

xorl S,D

D = D ^ S

异或

orl S,D

D = D | S

andl S,D

D = D & S

sall k,D

D = D << k

左移

shll k,D

D = D << k

左移(同sall)

sarl k,D

D = D >> k

算数右移

shrl k,D

D = D >> k

逻辑右移

 

 

特殊算术操作:

指令

效果

描述

imull S

R[%edx]:R[%eax] = S * R[%eax]

无符号64位乘

mull S

R[%edx]:R[%eax] = S * R[%eax]

有符号64位乘

cltd S

R[%edx]:R[%eax] = 符号位扩展R[%eax]

转换为4字节

idivl S

R[%edx] = R[%edx]:R[%eax] % S;

R[%eax] = R[%edx]:R[%eax] / S;

有符号除法,保存余数和商

divl S

R[%edx] = R[%edx]:R[%eax] % S;

R[%eax] = R[%edx]:R[%eax] / S;

无符号除法,保存余数和商

注:64位数通常存储为,高32位放在edx,低32位放在eax。

 

 

条件码:

条件码寄存器描述了最近的算数或逻辑操作的属性。

CF:进位标志,最高位产生了进位,可用于检查无符号数溢出。

OF:溢出标志,二进制补码溢出——正溢出或负溢出。

ZF:零标志,结果为0。

SF:符号标志,操作结果为负。

 

 

比较指令:

指令

基于

描述

cmpb S2,S1

S1 – S2

比较字节,差关系

testb S2,S1

S1 & S2

测试字节,与关系

cmpw S2,S1

S1 – S2

比较字,差关系

testw S2,S1

S1 & S2

测试字,与关系

cmpl S2,S1

S1 – S2

比较双字,差关系

testl S2,S1

S1 & S2

测试双字,与关系

 

 

访问条件码指令:

指令

同义名

效果

设置条件

sete D

setz

D = ZF

相等/零

setne D

setnz

D = ~ZF

不等/非零

sets D

 

D = SF

负数

setns D

 

D = ~SF

非负数

setg D

setnle

D = ~(SF ^OF) & ZF

大于(有符号>)

setge D

setnl

D = ~(SF ^OF)

小于等于(有符号>=)

setl D

setnge

D = SF ^ OF

小于(有符号<)

setle D

setng

D = (SF ^ OF) | ZF

小于等于(有符号<=)

seta D

setnbe

D = ~CF & ~ZF

超过(无符号>)

setae D

setnb

D = ~CF

超过或等于(无符号>=)

setb D

setnae

D = CF

低于(无符号<)

setbe D

setna

D = CF | ZF

低于或等于(无符号<=)

 

  

跳转指令:

指令

同义名

跳转条件

描述

jmp   Label

 

1

直接跳转

jmp   *Operand

 

1

间接跳转

je     Label

jz

ZF

等于/零

jne    Label

jnz

~ZF

不等/非零

js     Label

 

SF

负数

jnz    Label

 

~SF

非负数

jg     Label

jnle

~(SF^OF) & ~ZF

大于(有符号>)

jge    Label

jnl

~(SF ^ OF)

大于等于(有符号>=)

jl     Label

jnge

SF ^ OF

小于(有符号<)

jle     Label

jng

(SF ^ OF) | ZF

小于等于(有符号<=)

ja     Label

jnbe

~CF & ~ZF

超过(无符号>)

jae    Label

jnb

~CF

超过或等于(无符号>=)

jb     Label

jnae

CF

低于(无符号<)

jbe    Label

jna

CF | ZF

低于或等于(无符号<=)

 

 

转移控制指令:(函数调用):

指令

描述

call    Label

过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址

call    *Operand

leave

为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp

<think>我们正在讨论汇编语言中的预处理器指令,特别是`ifidni`、`lop`和`test`。需要注意的是,`lop`可能不是标准预处理器指令,可能是用户输入有误,可能是指`loop`指令(循环指令)或者是预处理器中的其他指令。而`test`是汇编语言中的指令,用于逻辑比较(相当于AND操作但不保存结果,只设置标志位)。预处理器指令通常以`.`开头(在MASM中)或`#`开头(在类似C的预处理中,但汇编中通常用MASM或NASM的语法)。根据引用[3]和引用[5],我们有关于`loop`指令和`test`指令的例子:-`loop`指令:用于循环,它会将CX/ECX/RCX寄存器减1,如果结果不为0则跳到指定标签(在引用[3]的代码示例中使用`loops`实现循环)。-`test`指令:用于测试操作数的某些位,实际上是对两个操作数进行逻辑与操作,但结果不保存,只影响标志位(如ZF标志)。在引用[5]中,`TESTAL,01H`用于测试AL的最低位是否为1(奇偶性)。然而,用户提到的`ifidni`确实是汇编预处理器指令(在MASM中),它用于条件汇编。预处理器指令在汇编器处理源代码之前执行,用于条件编译、宏定义等。下面我们分别解释:1.`ifidni`(在MASM中):这是一个条件汇编指令,用于比较两个标识符(不区分大小写)。如果它们相同,则汇编器将汇编`ifidni`和`endif`之间的代码。格式如下:ifidni<参数1>,<参数2>;如果两个参数相同(不区分大小写),则汇编此部分代码endif2.`lop`:在标准汇编中,没有名为`lop`的预处理器指令。可能是用户笔误,实际想询问的是`loop`指令(循环指令)或者可能是宏定义的标签?我们重点解释`loop`指令:`loop`指令(属于CPU指令,不是预处理器指令):loop目标标签它的操作是:deccx;将CX寄存器减1jnz目标标签;如果CX不为0则跳注意:在32位和64位模式下,可以使用ECX或RCX,但通常用CX(16位)作为循环计数器。3.`test`:这是一个汇编指令(不是预处理器指令),用于测试操作数的位。例如:testal,1;测试al的最低位是否为1(结果影响ZF标志,如果最低位是1,则与操作后结果为1,ZF=0;否则为0,ZF=1)testeax,eax;常用于测试eax是否为0(如果eax为0,则ZF=1)4.另外,用户提到“自定义标签或占位符”。在汇编语言中:-标签:用于标记代码或数据的位置,通常以冒号结尾(如`start:`,`s:`等),可以作为跳指令的目标。-占位符:可能是指宏定义中的参数,在宏中,用形参作为占位符,当宏被调用时用实参替换。举例说明预处理器指令(条件汇编和宏)的使用:示例1:条件汇编ifidniMACRO_ARG1,"abc"movax,1;如果宏参数MACRO_ARG1与字符串"abc"(不区分大小写)相同,则汇编这条指令elsemovax,0endif示例2:宏定义(使用占位符);定义一个宏,有两个参数mymacroMACROarg1,arg2movax,arg1movbx,arg2ENDM;调用宏mymacro10,20;这里10和20是实参,替换宏中的arg1和arg2总结:1.`ifidni`是MASM中的条件汇编指令(预处理器指令),用于比较两个标识符(不区分大小写),根据比较结果决定是否汇编某段代码。2.没有名为`lop`的预处理器指令,可能是`loop`指令的笔误。`loop`是循环指令,属于CPU指令。3.`test`是汇编语言中的逻辑测试指令(CPU指令),用于测试操作数的位,影响标志寄存器。4.自定义标签:程序员定义的名字,用来标记代码或数据的位置,用于跳或数据访问。5.占位符:在宏定义中使用的参数,在宏调用时用实际参数替换。注意:预处理器指令在汇编之前处理,而像`loop`、`test`这样的指令是在程序运行时执行的。下面是相关问题的生成:§§相关问题§§1.`ifidni`和`ifidn`有什么区别?2.除了`loop`指令,汇编语言还有哪些循环控制指令?3.宏定义中如何使用占位符?请举例说明。4.条件汇编指令除了`ifidni`,还有哪些?5.如何用`test`指令判断一个数是正数还是负数?</think> ### 汇编语言预处理指令解析 根据您的查询,我将系统解释以下汇编语言的预处理器指令和关键词含义: #### 1. **`ifidni`:条件汇编指令** - **作用**:在预编译阶段进行不区分大小写的字符串比对 - **语法**:`ifidni <参数1>, <参数2>` - **原理**:当两个参数字符串完全相等(忽略大小写)时,编译器会处理其后的代码块 - **示例**: ```nasm ifidni %%REG, "ax" mov %%REG, 0 ; 当参数为AX/ax时执行 endif ``` #### 2. **`lop`:非标准关键词(可能为误写)** - 标准汇编中不存在`lop`指令,可能指以下两种常见用途: a. **`loop`循环指令**(引用[3]) - 功能:基于CX寄存器计数循环 ```nasm mov cx, 5 myloop: ... ; 循环代码 loop myloop ; CX自减后非0则跳 ``` b. **自定义宏标签** ```nasm %macro my_lop 2 %1: ; 定义标签(如 my_lop start) %2 %endmacro ``` #### 3. **`test`:处理器指令 vs 宏指令** a. **处理器指令**(引用[5]) - **功能**:执行隐式AND运算并设置标志位 - **语法**:`test op1, op2` - **应用**: ```nasm test al, 01h ; 检测AL最低位是否为1 jz even ; 结果为0跳(偶数) ``` b. **预处理器宏**(自定义场景) - **作用**:创建条件编译占位符 ```nasm %define TEST_MODE 1 %if TEST_MODE db "Debug mode" ; 预编译阶段包含该字符串 %endif ``` #### 4. **占位符机制(预处理器核心)** - **符号占位符**:`%`开头的临时符号 ```nasm %define ptr_reg bx ; 编译时替换所有ptr_reg mov ax, [ptr_reg] ; → mov ax, [bx] ``` - **参数占位符**:宏中的`%1`, `%2` ```nasm %macro push_pair 2 push %1 push %2 %endmacro ``` > **关键区别**:预处理器指令(如`ifidni`, `%macro`)在编译前由预处理器解析;而处理器指令(如`test`, `loop`)在运行时由CPU执行[^3][^5]。 --- ### 相关问题 1. `ifidni`和`ifdef`在条件汇编中有何本质区别? 2. 如何利用预处理器实现跨平台汇编代码的自动适配? 3. `test`指令与`cmp`指令的标志位设置有何不同? 4. 循环展开优化时如何避免`loop`指令的性能陷阱? [^1]: 循环指令底层机制解析 [^3]: loop指令实际应用示例 [^5]: test指令在数据检测中的应用场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值