Chinaunix首页 | 论坛 | 博客
  • 博客访问: 506053
  • 博文数量: 176
  • 博客积分: 4045
  • 博客等级: 上校
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-19 11:23
文章分类

全部博文(176)

文章存档

2011年(7)

2009年(12)

2008年(157)

我的朋友

分类:

2008-06-16 15:46:21

作者:胡巧信 
    要弄懂linux内核代码,不懂汇编是不行的,linux下的汇编仅仅是语法跟intel有些不一样,它是at&t格式的。现在网上关于 at&t格式的汇编指令教程很多,但是你要用它才能真正理解它。我觉得看例子比较容易懂,所以花了一点时间弄明白了gcc内嵌汇编的语法,准备将 所有的指令陆续尝试,用内嵌的形式写出来,这样比较省事。这种方法结合反汇编,实在是学习汇编的最好方法,如果你感到很爽就请说出来,并且欢迎你把意见发 到,我会陆续将我的经验贡献给大家。
*************************************************************************
语法简单介绍:(最好自己去找详细的)

寄存器命名:寄存器名称有 % 前缀。即,如果必须使用 eax,它应该用作 %eax。

操作数的顺序:与intel 相反,可见仇恨有多大~~
操作数大小:根据操作数是字节 (byte)、字 (word) 还是长型 (long),指令的后缀可以是 b、w 或 l.这并不是强制性的;但为了自己好也要带上啊是不是?以后还要看得嘛!
立即操作数:通过使用 $ 指定直接操作数。
间接内存引用 :任何对内存的间接引用都是通过使用 ( ) 来完成的。
内嵌汇编语法:
 asm (
 assembler template
     : output operands               (optional)
        : input operands                (optional)
     : list of clobbered registers  
        (optional)
        ); 
例子:
 int count=1;
 int value=1;
 int buf[10];
 void main()
 {
 asm(
 cld nt
 rep nt
 stosl
 :
 : c (count), a (value) , d (buf[0])
 : %ecx,%edi );
 }

 其中符号c(count)指示要把count的值放入ecx寄存器
 类似的还有:
 a eax
 b ebx
 c ecx
 d edx
 S esi
 D edi
 q(从eax,ebx,ecx,edx中自动分配)
 r(从eax,ebx,ecx,edx,esi,edi自动分配)
 g (eax,ebx,ecx,edx或内存变量)
 a 把eax和edx合成一个64位的寄存器(use long longs)

 数字%n的用法:数字表示的寄存器是按照出现和从左到右的顺序映射到用r或q请求
的寄存器。
 如果强制使用固定的寄存器的话,如不用%1,而用ebx,则注意要使用两个%,因为一个%的语法

已经被%n用掉了.


以下是我写的例子,你看看就明白了,很容易的,但是对你理解以上东西很有帮助。
*************************************************************************
//andl
int main()
{
 int in=0x12345678;
 asm(
 "andl $-16,%0 \n"
 :
 :"m"(in)
 );
 printf("the %x is %x after andl\n ",in);
}

************************************************************************
//cmpl
int main()
{
 int in=100;
 char out;
 asm(
 "cmp $101,%1\n"
 "lahf\n"
 "movb %%ah,%%al\n"
 : "=a"(out)
 : "r"(in)
 );
 if(!(out&0x80))printf("in >=101\n");
 else printf("in<101\n");
}
****************************************************************************
//lds
int main()
{
 char src;
 short base;
 short off;
 asm(
 "lds %0,%%di\n"
 "mov %%ds,%1\n"
 "mov %%di,%2\n"
 :
 :"m"(src),"r"(base),"r"(off)
 :"%edx","%edi"
 );
 printf("the base is %x\n",base);
 printf("the off  is %x\n",off);
}
//该程序出现段错误,是因为在保护模式下不允许写ds寄存器吗?
******************************************************************************
//neg
int main()
{
 short in = 0x000f;
 printf("before neg :in is %x\n",in);
 asm(
 "neg %0\n"
 :"=r"(in)
 :"0"(in)
 );
 printf("after neg :in is %x\n",in);
}
*********************************************************************************
//sar shr
int main()
{
 int in1=-0xf00;
 int in2=-0xf00;
 int in3=-0xf00;
 printf("in1 is %x,in2 is %x \n",in1,in2);
 asm(
 "sarl $8,%0\n"
 "shrl $8,%1\n"
 :
 :"m"(in1),"m"(in2)
 );
 printf("in1 is %x,in2 is %x\n",in1,in2); 
}

***********************************************************************************
//xchgl
int main()
{
 char *p="abcd";
 char *q="1234";
 printf("p is %s,q is %s\n",p,q);
 asm(
 "xchgl %0,%1\n"
 :"=r"(q)
 :"m"(p),"0"(q)
 );
 printf("p is %s,q is %s\n",p,q);
}

***********************************************************************************
//adc
int main()
{
 int in1=100;
 int in2=200;
 printf("in1 is %d,in2 is %d\n",in1,in2);
 asm(
 "movw %0,%%ax\n"
 "addw %2,%%ax\n"
 "movw %%ax,%0\n"
 "leal %0,%%ecx\n"
 "leal %2,%%edx\n"
 "movw 2(%%edx),%%ax\n"
 "adcw %%ax,2(%%ecx)\n"
 :"=m"(in1)
 :"0"(in1),"m"(in2)
 );
 printf("in1 is %d,in2 is %d\n",in1,in2);
}
//这个过程中用到了leal,这个指令用来取变量的地址到寄存器中,要取某个变量附近的内容时很管用。
************************************************************************************
//lea
int main()
{
 char *p;
 printf("the address of p is %x\n",&p);
 asm(
 "leal %1,%%eax\n"
 "movl %%eax,%0\n"
 :"=m"(p)
 :"0"(p)
 );
 printf("the value of p is %x\n",p);
}
//将p的值取出来,放在p中,是不是让你对c语言的指针豁然开朗呢?
*************************************************************************************
//not
int main()
{
 int in=0x89abcdef;
 printf("the in is %x\n",in);
 asm(
 "notl %1\n"
 :"=r"(in)
 :"0"(in) 
 );
 printf("the in is %x\n",in);
}

*************************************************************************************
//sbb
int main()
{
 int in1=100;
 int in2=200;
 printf("in1 is %d,in2 is %d\n",in1,in2);
 asm(
 "movw %0,%%ax\n"
 "subw %2,%%ax\n"
 "movw %%ax,%0\n"
 "leal %0,%%ecx\n"
 "leal %2,%%edx\n"
 "movw 2(%%edx),%%ax\n"
 "sbbw %%ax,2(%%ecx)\n"
 :"=m"(in1)
 :"0"(in1),"m"(in2)
 );
 printf("after in1-in2-->in1\n");
 printf("in1 is %d,in2 is %d\n",in1,in2);
}
**************************************************************************************
//xlat
char str[10]="abcdefghi";
char p;
int main()
{
 asm(
 "movl %1,%%ebx\n"
 "movb $2,%%al\n"
 "xlat\n"
 :"=a"(p)
 :"r"(str)
 ); 
 printf("%c\n",p);
}
*************************************************************************************
//lahf
int main()
{
 char out = 0xff;
 asm(
 "mov $3,%%bx\n"
 "sub $1,%%bx\n"
 "lahf\n"
 "movb %%ah,%%al\n"
 :"=a"(out)
 :
 );
 printf("out is %x\n",out);
}
//如果你知道out的每个位的含义,就可以分析。查一下资料就行了。
**************************************************************************************
//mul
int main()
{
 short in1=300;
 short in2=500;
 int result;
 asm(
 "movw %1,%%ax\n"
 "mulw %2\n"
 "leal %0,%%eax\n"
 "mov %%ax ,(%%eax)"
 "mov %%dx,2(%%ecx)\n"
 :"=m"(result)
 :"m"(in1),"m"(in2)
 );
 printf("%d * %d = %d\n",in1,in2,result);
}

阅读(2087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~