����11-3 linux/kernel/math/ea.c


  1 /*

  2  * linux/kernel/math/ea.c

  3  *

  4  * (C) 1991 Linus Torvalds

  5  */

  6

  7 /*

  8  * Calculate the effective address.

  9  */

    /*

     * ������Ч��ַ��

     */

 10

 11 #include <stddef.h>         // ��׼����ͷ�ļ���������ʹ�������е�offsetof()���塣

 12

 13 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�

 14 #include <asm/segment.h>    // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����

 15

    // info�ṹ�и����Ĵ����ڽṹ�е�ƫ��λ�á�offsetof()������ָ���ֶ��ڽṹ�е�ƫ��λ

    // �á��μ�include/stddef.h�ļ���

 16 static int __regoffset[] = {

 17         offsetof(struct info,___eax),

 18         offsetof(struct info,___ecx),

 19         offsetof(struct info,___edx),

 20         offsetof(struct info,___ebx),

 21         offsetof(struct info,___esp),

 22         offsetof(struct info,___ebp),

 23         offsetof(struct info,___esi),

 24         offsetof(struct info,___edi)

 25 };

 26

    // ȡinfo�ṹ��ָ��λ�ô��Ĵ������ݡ�

 27 #define REG(x) (*(long *)(__regoffset[(x)]+(char *) info))

 28

    // ��2�ֽ�Ѱַģʽ�е�2������ָʾ�ֽ�SIB��Scale��Index��Base����ֵ��

 29 static char * sib(struct info * info, int mod)

 30 {

 31         unsigned char ss,index,base;

 32         long offset = 0;

 33

    // ���ȴ��û��������ȡ��SIB�ֽڣ�Ȼ��ȡ�������ֶα���λֵ��

 34         base = get_fs_byte((char *) EIP);

 35         EIP++;

 36         ss = base >> 6;                    // �������Ӵ�Сss��

 37         index = (base >> 3) & 7;           // ����ֵ��������index��

 38         base &= 7;                         // ����ַ����base��

    // �����������Ϊ0b100����ʾ������ƫ��ֵ����������ƫ��ֵoffset=��Ӧ�Ĵ�������*�������ӡ�

 39         if (index == 4)

 40                 offset = 0;

 41         else

 42                 offset = REG(index);

 43         offset <<= ss;

    // �����һMODRM�ֽ��е�MOD��Ϊ�㣬����Base������0b101�����ʾ��ƫ��ֵ��baseָ����

    // �Ĵ����С����ƫ��offset��Ҫ�ټ���base��Ӧ�Ĵ����е����ݡ�

 44         if (mod || base != 5)

 45                 offset += REG(base);

    // ���MOD=1�����ʾƫ��ֵΪ1�ֽڡ�������MOD=2������base=0b101����ƫ��ֵΪ4�ֽڡ�

 46         if (mod == 1) {

 47                 offset += (signed char) get_fs_byte((char *) EIP);

 48                 EIP++;

 49         } else if (mod == 2 || base == 5) {

 50                 offset += (signed) get_fs_long((unsigned long *) EIP);

 51                 EIP += 4;

 52         }

    // ��󱣴沢����ƫ��ֵ��

 53         I387.foo = offset;

 54         I387.fos = 0x17;

 55         return (char *) offset;

 56 }

 57

    // ����ָ����Ѱַģʽ�ֽڼ�����Ч��ֵַ��

 58 char * ea(struct info * info, unsigned short code)

 59 {

 60         unsigned char mod,rm;

 61         long * tmp = &EAX;

 62         int offset = 0;

 63

    // ����ȡ�����е�MOD�ֶκ�R/M�ֶ�ֵ�����MOD=0b11����ʾ�ǵ��ֽ�ָ�û��ƫ���ֶΡ�

    // ���R/M�ֶ�=0b100������MOD��Ϊ0b11����ʾ��2�ֽڵ�ַģʽѰַ����˵���sib()��

    // ��ƫ��ֵ�����ؼ��ɡ�

 64         mod = (code >> 6) & 3;          // MOD�ֶΡ�

 65         rm = code & 7;                  // R/M�ֶΡ�

 66         if (rm == 4 && mod != 3)

 67                 return sib(info,mod);

    // ���R/M�ֶ�Ϊ0b101������MODΪ0����ʾ�ǵ��ֽڵ�ַģʽ�����Һ���32�ֽ�ƫ��ֵ��

    // ����ȡ���û�������4�ֽ�ƫ��ֵ�����沢����֮��

 68         if (rm == 5 && !mod) {

 69                 offset = get_fs_long((unsigned long *) EIP);

 70                 EIP += 4;

 71                 I387.foo = offset;

 72                 I387.fos = 0x17;

 73                 return (char *) offset;

 74         }

    // ������������������MOD���д���������ȡ��R/M�����Ӧ�Ĵ������ݵ�ֵ��Ϊָ��tmp��

    // ����MOD=0����ƫ��ֵ������MOD=1���������1�ֽ�ƫ��ֵ������MOD=2���������4�ֽ�

    // ƫ��ֵ����󱣴沢������Ч��ֵַ��

 75         tmp = & REG(rm);

 76         switch (mod) {

 77                 case 0: offset = 0; break;

 78                 case 1:

 79                         offset = (signed char) get_fs_byte((char *) EIP);

 80                         EIP++;

 81                         break;

 82                 case 2:

 83                         offset = (signed) get_fs_long((unsigned long *) EIP);

 84                         EIP += 4;

 85                         break;

 86                 case 3:

 87                         math_abort(info,1<<(SIGILL-1));

 88         }

 89         I387.foo = offset;

 90         I387.fos = 0x17;

 91         return offset + (char *) *tmp;

 92 }

 93