_set_gate(gate_addr,type,dpl,addr)

对学习书上的部分不懂,搜索到的,文章出处

http://www.cnblogs.com/hongzg1982/articles/2120993.html

#define _set_gate(gate_addr,type,dpl,addr)
__asm__("movw %%dx,%%ax "
        "movw %0,%%dx "
        "movl %%eax,%1 "
        "movl %%edx,%2"
        :
        :"i"((short)(0x8000+(dpl<<13)+(type<<8))),
         "o"(*((char *)(gate_addr))),
         "o"(*(4+(char *)(gate_addr))),
         "d"((char *)(addr)),"a"(0x00080000))


汇编注释:
1、mov :为寄存器移动指令,例如movw dx,ax 即为dx-〉ax,mov为移动指令。“w”为长度的指定w=word=16位=2个字节;相应的“l”=long=32位=4字节。
2、% :AT&T汇编在引用寄存器时要在前面加1个%,%%是因为GCC在编译时会将%视为特殊字符,拥有特殊意义,%%仅仅是为了汇编的%不被GCC全部转译掉
3、ax 与 eax :ax与eax之间是有联系的,他们并不是孤立的,eax为32位寄存器,ax为16位寄存器,而ax就是eax的低16位。dx与edx具有相同的关系。
4、%0、%1、%2、%3:0、1、2、3可以看作变量,这些变量在程序的":"之后,程序的两个":",是定义输入、输出项的。针对这段程序这些变量的前面都加了明确的限定,例如"i"(输入项)、"o"(输出项),剩下的"d"(edx的初始值),"a"(eax的初始值)。而0、1、2、3的概念就是指第几个变量,这里输入项、输出向、寄存器初始混合编号;相应的0("i"((short)(0x8000+(dpl<<13)+(type<<8)))));1((*((char *)(gate_addr))));2((*(4+(char *)(gate_addr))));3("d"((char *)(addr)));4("a"(0x00080000))
5、<<:这是个运算符,如果大家觉得<<不好理解可以用乘2的次方来实现相同的效果,例如14<<13=14*2的13次方
6、 :这是嵌入式汇编一种书写格式


===================================================

进入汇编程序段后

"d"((char *)(addr)) 代表把偏移地址addr值放入edx中,一共32位(高16位,低16位)

"a"(0x00080000)   代表把0x00080000值放入eax中,一共32位(高16位就是0x0008是段选择符,低16位会被放在edx中的过程偏移低16位代替)

"i"((short)(0x8000+(dpl<<13)+(type<<8))) 中断或者陷进的属性及dpl ,0x8000指示存在,一共32位(高16位为0x0000,低16位放前边说的,会被放入地址的低16位中)

另外两条用于输出

         "o"(*((char *)(gate_addr)))
         "o"(*(4+(char *)(gate_addr))) 放入对应的IDT[]中

movw %%dx,%%ax     movw只移动低16位,高16位不变 eax中的0x00080000变成了0x008和低16位地址

movw %0,%%dx         把第一个参数(%0)低16位放入dx, edx中现在是高16位偏移地址和保存进来的杂项
===================================================

原文地址:https://www.cnblogs.com/caesarxu/p/3251703.html