内核中的汇编代码是AT&T格式的,和Intel的不太一样。本来想从网上直接转过来AT&T汇编指令说明,可是发现太多了,我只是需要了解一下而已。所以,下面我摘取一段很短的内核代码,先对此有个认识,以后遇到更复杂的再继续完善。
linux-0.11/fs/bitmap.c
#define clear_block(addr) \
__asm__("cld\n\t" \
rep\n\t \
stosl" \
::"a" (0), "c" (BLOCK_SIZE/4), "D" ( (long) (addr) : "cx", "di")
该段代码的汇编代码为:
movl $0, %eax
movl (BLOCK_SIZE/4), %ecx
movl addr, %edi
这样,我们说明一下该代码的含义:
向addr中写入(BLOCK_SIZE/4)个0,即将指定地址addr处的一块1024字节内存清零。
解释一下出现的指令含义:
cld: clear direction //清方向位
rep: repeat //重复执行下面的存储数据
stosl: store string //存储数据,相当于将EAX中的值保存到ES:EDI指向的地址中
下面说一下基本的行内汇编 :
基本的行内汇编很简单,一般是按照下面的格式 :
asm("statements") 例如:asm("nop")
注:1. asm 和 __asm__是完全一样的
2. 如果有多行汇编,则每一行都要加上 "\n\t"
实际上gcc在处理汇编时,是要把asm(...)的内容"打印"到汇编文件中,所以格式控制字符是必要的.
再扩展的行内汇编 :
扩展的行内汇编类似于Watcom.
基本的格式是:
asm ( "statements" : output_regs : input_regs : clobbered_regs)
注:冒号后的语句指明输入,输出和被改变的寄存器.通过冒号以后的语句,编译器就知道你的指令需要和改变哪些寄存器,从而可以寄存器的分配.
例子__asm__("...": :"a" (0), "c" (BLOCK_SIZE/4), "D" ( (long) (addr) : "cx", "di") 中的
"a" (0):把0放入%eax中
"c" (BLOCK_SIZE/4):把(BLOCK_SIZE/4)放入%ecx中
"D" ( (long) (addr):把addr放入%edi中
说明一下字母代表的含义:
a :eax ; b :ebx ;c : ecx;d :edx ;S :esi ; D :edi
“...”即statements, 第一个 : 后没有东西,表明没有输出寄存器,
第二个 :后为"a" (0), "c" (BLOCK_SIZE/4), "D" ( (long) (addr) ,表明%eax, %ecx, %edi是输入寄存器
第三个:后是"cx", "di",表明是被改变的寄存器
下面,说一个稍微复杂一点的。
linux-0.11/fs/super.c
#define set_bit(bitnr, addr) ( { \
register int __res __asm__("ax");
__asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
__res; } )
首先,我们说明一下这段代码的含义:
测试指定位偏移处比特位的值,并返回该原比特位的值。命名为test_bit()更好。
具体的解释一下这段代码:
1. set_bit(bitnr, addr) 参数的含义:
bitnr - 比特位偏移值; addr - 测试比特位操作的起始地址。
2. register int __res __asm__("ax"):
定义了一个局部寄存器变量。该变量将被保存在eax寄存器中,以便于高效访问和操作。
这种定义变量的方法主要用于内嵌汇编程序中。__res值尽量放在eax中。
3. __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
__res; } ) :
(1) 指令bt (bit test) : 用于对比特位进行测试。
(2) “=” :表示输出寄存器。
(3) 数字%n的用法:数字表示的寄存器是按照出现和从左到右的顺序映射到请求
的寄存器。
那么,例子中的 %0 : __res, %1 : 0, %2 : bitnr, %3 :addr
(4) bt %2, %3 : bt会把比特位偏移量 bitnr(%2)和地址addr(%3)指定的比特位的值放入进位标志(CF)中。
(5) 指令setb: 根据进位标志CF设置操作数%al。若CF = 1, %al = 1; CF = 0, %al = 0。
阅读(2303) | 评论(0) | 转发(0) |