����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