x86汇编指令集

asm();括号里面每条指令后不加上\n\t会怎么样
例如下面的代码exam_x86.c

int main()
{
__asm__("cld\n\t"
        "cld\n\t"
);
    return 0; 
}

内核完全注释上说是为了预处理时候对齐指令的,这个说法其实不对,gcc -E选项编译完,还是源程序这个样子

book@book-desktop:~/sgy/first_video/exam/inline_asm$ gcc -E exam_x86.c
# 1 "exam_x86.c"
# 1 ""
# 1 ""
# 1 "exam_x86.c"
int main()
{
__asm__("cld\n\t"
  "cld\n\t"
);
 return 0;
}

可见预处理没有处理,使用-S选项停在汇编程序阶段应该能够看出来差别,这里我们将第一行cld的/n/t去掉

gcc -S exam_x86.c

生成的汇编文件---exam_x86.s程序的源码
    .file   "exam_x86.c"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
#APP
# 3 "exam_x86.c" 1
    cldcld
    
# 0 "" 2
#NO_APP
    movl    $0, %eax
    popl    %ebp
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
    .section    .note.GNU-stack,"",@progbits

从这里看出来你不加上的话,就变成一条cldcld指令,编译的时候就会提示你没有cldcld这条指令

# 3 "exam_x86.c" 1
    cldcld

那么第二行的cld需不需要加呢?试验一下就知道了.貌似是可以不加的,当然,到这里我们已经了解到这个在前面几个指令是必须加上的,所以干脆全部加上,保险起见..

结论:

\n是为了让指令分开,不被解析成一条指令,而\t选项是为了对齐好看的.

ret指令
不带任何参数时,用于在子程序的结束位置,被调用的子程序必须有ret指令,否则调用没有ret指令的子程序会导致自陷,子程序执行完之后处于失控状态。带参数ret n 表示子程序返回主程序的同时,堆栈弹出n个字节(栈顶指针减n)

rep指令的目的是重复其上面的指令.ECX的值是重复的次数.

cld相对应的指令是std,二者均是用来操作方向标志位DF(Direction Flag)。cld使DF 复位,即是让DF=0,std使DF置位,即DF=1.这两个指令用于串操作指令中。通过执行cld或std指令可以控制方向标志DF,决定内存地址是增大(DF=0,向高地址增加)还是减小(DF=1,向地地址减小)。

王爽的书
11.10 DF标志和串传送指令

LODS (Load string)串装入指令:将数据从内存指定位置装入CPU中的累加器
指令格式有3种:
LODS OPRD ;OPRD为源串
LODSB
LODSW
LODS指令把由DS:SI指向的源串中的字节或字取到累加器AL或AX中,并在这之后根据DF的值自动修改指针SI,以指向下一个要装入的字节或字。

指令名称:存串指令
用法:stos dst,dst是一个目的地址
【指令格式】STOS 目的串
STOSB ; 存字节串
STOSW ;存字串
stos指令的含义是:将寄存器(AX,EAX)里的内容(一个字或一个字节)存储(store)到内存单元(地址ES:DI),同时CPU自动修改DI,以指向下一元素,即:((DI))←(AX或AL),(DI)←(DI)±1或2。[1]作为参考,与之反操作的指令是lods,它的含义是将内存单元(地址:DS:SI)中的内容装入(load)到寄存器(AX,EAX)。
stos根据操作单元的大小有几种方式byte/word/dword等

SCAS指令用于搜索一个特定的字符或字符串中的字符集。要搜索的数据项应该是在AL,AX(SCASW)或EAX寄存器(SCASD)的(SCASB)。被搜索的字符串应该是在内存中,并指出由ES:DI(或EDI)寄存器。

lea指令(类似offset指令) 当前esp的寄存器值为0x28ff00
lea 0x18(%esp),%eax
执行完eax = 0x28ff18

AT&T汇编enter指令和leave指令

enter指令

在AT&T汇编中,enter等效于以下汇编指令:

pushl %ebp # 将%ebp压栈
movl %esp %ebp # 将%esp保存到%ebp, 这两步是函数的标准开头

leave指令

在AT&T汇编中,leave等效于以下汇编指令:

movl %ebp, %esp
popl %ebp

call指令

在AT&T汇编中,call foo(foo是一个标号)等效于以下汇编指令:

pushl %eip
movl f, %eip

ret指令

在AT&T汇编中,ret等效于以下汇编指令:

popl %eip

movl指令
l是长字(4字节),
w是双字
b是一个字节

加在指令的后边
相当于intel中的
dword ptr
word ptr
byte ptr

int指令
❑ EAX contains the system call value.
❑ EBX contains the file descriptor to write to.
❑ ECX contains the start of the string.
❑ EDX contains the length of the string

movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80

    To access these kernel functions, you must use the int instruction code, which generates a software interrupt, with a value of 0x80. 
    The specific function that is performed is determined by the value of the EAX register. Without this kernel function, 

越是最后入栈,它越是靠近c函数参数左侧

jmpi指令
jmpi go,INITSEG jmpi为段间跳转指令 执行这条指令之后 CS = INITSEG IP = go 也就是跳转到地址 INITSEG : go……

int 0x13指令
入口参数:
AH=02H 指明调用读扇区功能。
AL 置要读的扇区数目,不允许使用读磁道末端以外的数值,也不允许使该寄存器为0。

CH 磁道号的低8位数。

CL 低5位放入所读起始扇区号,位7-6表示磁道号的高2位。cl=开始扇区(位0—5),磁道号高二位(位6—7)

DL 需要进行读操作的驱动器号。dl=驱动器号(若是硬盘则要置位7)
DH 所读磁盘的磁头号。dh=磁头号

es:Bx—>指向数据缓冲区 ES:BX 读出数据的缓冲区地址。

若出错则CF示志置位

返回参数:
如果CF=1,AX中存放出错状态。读出后的数据在ES:BX区域依次排列

jnc指令
JNC Jump if not carry CF=0

STI(Set Interrupt) 中断标志置1指令 使 IF = 1;
CLI(Clear Interrupt) 中断标志置0指令 使 IF = 0.

它们只影响本指令指定的标志,而不影响其他标志位(即STI和CLI只影响IF)。

1、 JNE指令/JNZ功能

条件转移指令JNE/JNZ //不等于转移

格式: JNE/JNZ 标号

功能: ZF=0,转至标号地址处执行
xor指令
xor ax,ax ===>ax = ax 异或 ax
这里进行的是清0操作

lidt指令 加载中段描述符表寄存器IDTR,把IDT表的基地址和长度从内存加载到IDTR中

IDTR,GDTR,TR,LDTR


x86汇编指令集_第1张图片
内存管理寄存器

lmsw指令 加载机器状字(对应CR0寄存器15-0)

LEA reg,mem
mem有效地址->reg

LDS reg,mem
mem低字->reg,mem高字->ds

LES reg,mem
mem低字->reg,mem高字->es

LFS reg,mem
mem低字->reg,mem高字->fs

LGS reg,mem
mem低字->reg,mem高字->gs

LSS reg,mem
mem低字->reg,mem高字->ss

7.28 .fill repeat , size , value
repeat, size 和value都必须是纯粹的表达式。本命令生成size个字节的repeat个副本。
Repeat可以是0或更大的值。Size 可以是0或更大的值, 但即使size大于8,也被视作8,以
兼容其它的汇编器。各个副本中的内容取自一个8字节长的数。最高4个字节为零,最低的
4个字节是value,它以as正在汇编的目标计算机的整数字节顺序排列。每个副本中的size
个字节都取值于这个数最低的size个字节。再次说明,这个古怪的动作只是为了兼容其他
的汇编器。
size参数和value参数是可选的。如果不存在第2个逗号和value参数,则假定value为零。
如果不存在第1个逗号和其后的参数,则假定size为1。

loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作
1:(cx)=(cx)-1
2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行

JE ;等于则跳转
JNE ;不等于则跳转

JZ ;为 0 则跳转
JNZ ;不为 0 则跳转

JS ;为负则跳转
JNS ;不为负则跳转

JC ;进位则跳转
JNC ;不进位则跳转

JO ;溢出则跳转
JNO ;不溢出则跳转

JA ;无符号大于则跳转
JNA ;无符号不大于则跳转
JAE ;无符号大于等于则跳转
JNAE ;无符号不大于等于则跳转

JG ;有符号大于则跳转
JNG ;有符号不大于则跳转
JGE ;有符号大于等于则跳转
JNGE ;有符号不大于等于则跳转

JB ;无符号小于则跳转
JNB ;无符号不小于则跳转
JBE ;无符号小于等于则跳转
JNBE ;无符号不小于等于则跳转

JL ;有符号小于则跳转
JNL ;有符号不小于则跳转
JLE ;有符号小于等于则跳转
JNLE ;有符号不小于等于则跳转

JP ;奇偶位置位则跳转
JNP ;奇偶位清除则跳转
JPE ;奇偶位相等则跳转
JPO ;奇偶位不等则跳转

test指令,测试指令
格式:TEST Dest, Src
实现源操作数于目的操作数的按位逻辑与运算,并按结果设置标志位。但是结果不送入目的地址中。即只作(SRC)^(DEST)。结果影响SF、ZF、PF
例如:测试AL中第3位状态,则使用TEST AL,03H。若ZF=1,表示该位是0;反之,该位是1。

repne,repe指令


x86汇编指令集_第2张图片
repne,repe指令

lsll指令
lsll 是加载段界限的指令,把 segment 段描述符中的段界限字段装入__limit,函数返回__limit 加 1,即段长。

5.2.6 位操作指令

2、位检测指令(Bit Test Instruction)

指令的格式:BT/BTC/BTR/BTS Reg/Mem, Reg/Imm    ;80386+受影响的标志位:CF
位检测指令是把第一个操作数中某一位的值传送给标志位CF,具体的哪一位由指令的第二操作数来确定。
根据指令中对具体位的处理不同,又分一下几种指令:
BT:把指定的位传送给CF;BTC:把指定的位传送给CF后,还使该位变反;BTR:把指定的位传送给CF后,还使该位变为0;BTS:把指定的位传送给CF后,还使该位变为1;

x86汇编指令集_第3张图片

图5.11 位检测指令的功能示意图

例如:假设(AX)=1234H,分别执行下面指令。
BT  AX, 2      ;指令执行后,CF=1,(AX)=1234h
BTC AX, 6       ;指令执行后,CF=0,(AX)=1274h
BTR AX, 10      ;指令执行后,CF=0,(AX)=1234h
BTS AX, 14      ;指令执行后,CF=0,(AX)=5234h

你可能感兴趣的:(x86汇编指令集)