/*******************************************************************************************
NSString
*******************************************************************************************/
/*----------------创建字符串的方法----------------*/
//1、创建常量字符串。
NSString *astring = @"This is a String!";
//2、创建空字符串,给予赋值。
NSString *astring = [[NSString alloc] init];
astring = @"This is a String!";
NSLog(@"astring:%@", astring);
[astring release];
//3、在以上方法中,提升速度:initWithString方法
NSString *astring = [[NSString alloc] initWithString:@"This is a String!"];
NSLog(@"astring:%@", astring);
[astring release];
//4、用标准c创建字符串:initWithCString方法
char *Cstring = "This is a String!";
NSString *astring = [[NSString alloc] initWithCString:Cstring];
NSLog(@"astring:%@",astring);
[astring release];
//5、创建格式化字符串:占位符(由一个%加一个字符组成)
int i = 1;
int j = 2;
NSString *astring = [[NSString alloc] initWithString:[NSString stringWithFormat:@"%d.This is %i string!", i, j]];
NSLog(@"astring:%@", astring);
[astring release];
//6、创建临时字符串
NSString *astring;
astring = [NSString stringWithCString:"This is a temporary string"];
NSLog(@"astring:%@", astring);
/*----------------从文件读取字符串:initWithContentsOfFile方法----------------*/
NSString *path = @"astring.text";
NSString *astring = [[NSString alloc] initWithContentsOfFile:path];
NSLog(@"astring:%@",astring);
[astring release];
/*----------------写字符串到文件:writeToFile方法----------------*/
NSString *astring = [[NSString alloc] initWithString:@"This is a String!"];
NSLog(@"astring:%@",astring);
NSString *path = @"astring.text";
[astring writeToFile: path atomically: YES];
[astring release];
/*----------------比较两个字符串----------------*/
// 1、用C比较:strcmp函数
char string1[] = "string!";
char string2[] = "string!";
if(strcmp(string1, string2) = = 0)
{
NSLog(@"1");
}
// 2、isEqualToString方法
NSString *astring01 = @"This is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 isEqualToString:astring02];
NSLog(@"result:%d",result);
// 3、compare方法(comparer返回的三种值)
// 1) NSOrderedSame判断两者内容是否相同
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedSame;
NSLog(@"result:%d",result);
// 2) NSOrderedAscending判断两对象值的大小(按字母顺序进行比较,astring02大于astring01为真)
NSString *astring01 = @"This is a String!";NSString *astring02 = @"this is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedAscending;
NSLog(@"result:%d",result);
// 3) NSOrderedDescending判断两对象值的大小(按字母顺序进行比较,astring02小于astring01为真)
NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedDescending;
NSLog(@"result:%d",result);
// 4、不考虑大小写比较字符串1
NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 caseInsensitiveCompare:astring02] = = NSOrderedSame;
NSLog(@"result:%d",result);
// NSOrderedDescending判断两对象值的大小(按字母顺序进行比较,astring02小于astring01为真)
// 5、不考虑大小写比较字符串2
NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02
options:NSCaseInsensitiveSearch | NSNumericSearch] = = NSOrderedSame;
NSLog(@"result:%d",result);
// NSCaseInsensitiveSearch:不区分大小写比较 NSLiteralSearch:进行完全比较,区分大小写 NSNumericSearch:比较字符串的字符个数,而不是字符值。
/*----------------改变字符串的大小写----------------*/
NSString *string1 = @"A String";
NSString *string2 = @"String";
NSLog(@"string1:%@",[string1 uppercaseString]);//大写
NSLog(@"string2:%@",[string2 lowercaseString]);//小写
NSLog(@"string2:%@",[string2 capitalizedString]);//首字母大小
/*----------------在串中搜索子串----------------*/
NSString *string1 = @"This is a string";
NSString *string2 = @"string";
NSRange range = [string1 rangeOfString:string2];
int location = range.location;
int leight = range.length;
NSString *astring = [[NSString alloc] initWithString:[NSString stringWithFormat:@"Location:%i,Leight:%i",location,leight]];
NSLog(@"astring:%@",astring);
[astring release];
/*----------------抽取子串 ----------------*/
// -substringToIndex: 从字符串的开头一直截取到指定的位置,但不包括该位置的字符
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringToIndex:3];
NSLog(@"string2:%@",string2);
// -substringFromIndex: 以指定位置开始(包括指定位置的字符),并包括之后的全部字符
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringFromIndex:3];
NSLog(@"string2:%@",string2);
// -substringWithRange: //按照所给出的位置,长度,任意地从字符串中截取子串
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringWithRange:NSMakeRange(0, 4)];
NSLog(@"string2:%@",string2);
//扩展路径
NSString *Path = @"~/NSData.txt";
NSString *absolutePath = [Path stringByExpandingTildeInPath];
NSLog(@"absolutePath:%@",absolutePath);
NSLog(@"Path:%@",[absolutePath stringByAbbreviatingWithTildeInPath]);
//文件扩展名
NSString *Path = @"~/NSData.txt";
NSLog(@"Extension:%@",[Path pathExtension]);
NSMutableString
*******************************************************************************************/
/*----------------给字符串分配容量----------------*/
//stringWithCapacity:
NSMutableString *String;
String = [NSMutableString stringWithCapacity:40];
/*----------------在已有字符串后面添加字符----------------*/
//appendString: and appendFormat:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
//[String1 appendString:@", I will be adding some character"];
[String1 appendFormat:[NSString stringWithFormat:@", I will be adding some character"]];
NSLog(@"String1:%@",String1);
*/
/*----------------在已有字符串中按照所给出范围和长度删除字符------*/
/*
//deleteCharactersInRange:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 deleteCharactersInRange:NSMakeRange(0, 5)];
NSLog(@"String1:%@",String1);
/*----------------在已有字符串后面在所指定的位置中插入给出的字符串------*/
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 insertString:@"Hi! " atIndex:0];
NSLog(@"String1:%@",String1);
/*----------------将已有的空符串换成其它的字符串------*/
//-setString:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 setString:@"Hello Word!"];
NSLog(@"String1:%@",String1);
/*----------------按照所给出的范围,和字符串替换的原有的字符------*/
//-setString:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 replaceCharactersInRange:NSMakeRange(0, 4) withString:@"That"];
NSLog(@"String1:%@",String1);
/*----------------判断字符串内是否还包含别的字符串(前缀,后缀)-------------*/
// 01:检查字符串是否以另一个字符串开头- (BOOL) hasPrefix: (NSString *) aString;
NSString *String1 = @"NSStringInformation.txt";
[String1 hasPrefix:@"NSString"] = = 1 ? NSLog(@"YES") : NSLog(@"NO");
[String1 hasSuffix:@".txt"] = = 1 ? NSLog(@"YES") : NSLog(@"NO");
// 02:查找字符串某处是否包含其它字符串 - (NSRange) rangeOfString: (NSString *) aString,这一点前面在串中搜索子串用到过;
NSArray
*******************************************************************************************/
/*----------------创建数组---------------------*/
// NSArray *array = [[NSArray alloc] initWithObjects:
@"One",@"Two",@"Three",@"Four",nil];
self.dataArray = array;
[array release];
// - (unsigned) Count;数组所包含对象个数;
NSLog(@"self.dataArray cound:%d",[self.dataArray count]);
// - (id) objectAtIndex: (unsigned int) index;获取指定索引处的对象;
NSLog(@"self.dataArray cound 2:%@",[self.dataArray objectAtIndex:2]);
/*----------------从一个数组拷贝数据到另一数组(可变数级)-----------------------*/
// arrayWithArray:
// NSArray *array1 = [[NSArray alloc] init];
NSMutableArray *MutableArray = [[NSMutableArray alloc] init];
NSArray *array = [NSArray arrayWithObjects:
@"a",@"b",@"c",nil];
NSLog(@"array:%@",array);
MutableArray = [NSMutableArray arrayWithArray:array];
NSLog(@"MutableArray:%@",MutableArray);
array1 = [NSArray arrayWithArray:array];
NSLog(@"array1:%@",array1);
// Copy
// id obj;
NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSArray *oldArray = [NSArray arrayWithObjects:
@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",nil];
NSLog(@"oldArray:%@",oldArray);
for(int i = 0; i < [oldArray count]; i++)
{
obj = [[oldArray objectAtIndex:i] copy];
[newArray addObject: obj];
}
//
NSLog(@"newArray:%@", newArray);
[newArray release];
// 快速枚举
// NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSArray *oldArray = [NSArray arrayWithObjects:
@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",nil];
NSLog(@"oldArray:%@",oldArray);
for(id obj in oldArray)
{
[newArray addObject: obj];
}
//
NSLog(@"newArray:%@", newArray);
[newArray release];
// Deep copy
// NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSArray *oldArray = [NSArray arrayWithObjects:
@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",nil];
NSLog(@"oldArray:%@",oldArray);
newArray = (NSMutableArray*)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFPropertyListRef)oldArray, kCFPropertyListMutableContainers);
NSLog(@"newArray:%@", newArray);
[newArray release];
// Copy and sort
// NSMutableArray *newArray = [[NSMutableArray alloc] init];
NSArray *oldArray = [NSArray arrayWithObjects:
@"b",@"a",@"e",@"d",@"c",@"f",@"h",@"g",nil];
NSLog(@"oldArray:%@",oldArray);
NSEnumerator *enumerator;
enumerator = [oldArray objectEnumerator];
id obj;
while(obj = [enumerator nextObject])
{
[newArray addObject: obj];
}
[newArray sortUsingSelector:@selector(compare:)];
NSLog(@"newArray:%@", newArray);
[newArray release];
/*----------------切分数组------------------------------*/
//从字符串分割到数组- componentsSeparatedByString:
NSString *string = [[NSString alloc] initWithString:@"One,Two,Three,Four"];
NSLog(@"string:%@",string);
NSArray *array = [string componentsSeparatedByString:@","];
NSLog(@"array:%@",array);
[string release];
//从数组合并元素到字符串- componentsJoinedByString:
NSArray *array = [[NSArray alloc] initWithObjects:@"One",@"Two",@"Three",@"Four",nil];
NSString *string = [array componentsJoinedByString:@","];
NSLog(@"string:%@",string);
/*******************************************************************************************
NSMutableArray
*******************************************************************************************/
/*----------------给数组分配容量----------------*/
//NSArray *array;
array = [NSMutableArray arrayWithCapacity:20];
//- (void) addObject: (id) anObject;
//NSMutableArray *array = [NSMutableArray arrayWithObjects:
@"One",@"Two",@"Three",nil];
[array addObject:@"Four"];
NSLog(@"array:%@",array);
/*----------------删除数组中指定索引处对象----------------*/
//-(void) removeObjectAtIndex: (unsigned) index;
//NSMutableArray *array = [NSMutableArray arrayWithObjects:
@"One",@"Two",@"Three",nil];
[array removeObjectAtIndex:1];
NSLog(@"array:%@",array);
/*----------------数组枚举---------------*/
//- (NSEnumerator *)objectEnumerator;从前向后
//NSMutableArray *array = [NSMutableArray arrayWithObjects:
@"One",@"Two",@"Three",nil];
NSEnumerator *enumerator;
enumerator = [array objectEnumerator];
id thingie;
while (thingie = [enumerator nextObject])
{
NSLog(@"thingie:%@",thingie);}
// - (NSEnumerator *)reverseObjectEnumerator;从后向前
//NSMutableArray *array = [NSMutableArray arrayWithObjects:
@"One",@"Two",@"Three",nil];
NSEnumerator *enumerator;
enumerator = [array reverseObjectEnumerator];
id object;
while (object = [enumerator nextObject]) {
NSLog(@"object:%@",object);
}
//快速枚举
//NSMutableArray *array = [NSMutableArray arrayWithObjects:
@"One",@"Two",@"Three",nil];
for(NSString *string in array)
{
NSLog(@"string:%@",string);
}
/*******************************************************************************************
NSDictionary
*******************************************************************************************/
/*----------------创建字典------------------------------------*/
//- (id) initWithObjectsAndKeys;
//NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"One",@"1",@"Two",@"2",@"Three",@"3",nil];
NSString *string = [dictionary objectForKey:@"One"];
NSLog(@"string:%@",string);
NSLog(@"dictionary:%@",dictionary);
[dictionary release];
/*******************************************************************************************
NSMutableDictionary
*******************************************************************************************/
/*----------------创建可变字典------------------------------------*/
//创建
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
//添加字典
[dictionary setObject:@"One" forKey:@"1"];
[dictionary setObject:@"Two" forKey:@"2"];
[dictionary setObject:@"Three" forKey:@"3"];
[dictionary setObject:@"Four" forKey:@"4"];
NSLog(@"dictionary:%@",dictionary);
//删除指定的字典
[dictionary removeObjectForKey:@"3"];
NSLog(@"dictionary:%@",dictionary);
/*******************************************************************************************
NSValue(对任何对象进行包装)
*******************************************************************************************/
/*----------------将NSRect放入NSArray中------------------------------------*/
//将NSRect放入NSArray中
NSMutableArray *array = [[NSMutableArray alloc] init];
NSValue *value;
CGRect rect = CGRectMake(0, 0, 320, 480);
value = [NSValue valueWithBytes:&rect objCType:@encode(CGRect)];
[array addObject:value];
NSLog(@"array:%@",array);
//从Array中提取
value = [array objectAtIndex:0];
[value getValue:&rect];
NSLog(@"value:%@",value);
/*******************************************************************************************
从目录搜索扩展名为jpg的文件
*******************************************************************************************/
//NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *home;
home = @"../Users/";
NSDirectoryEnumerator *direnum;
direnum = [fileManager enumeratorAtPath: home];
NSMutableArray *files = [[NSMutableArray alloc] init];
//枚举
NSString *filename;
while (filename = [direnum nextObject]) {
if([[filename pathExtension] hasSuffix:@"jpg"]){
[files addObject:filename];
}
}
//快速枚举
//for(NSString *filename in direnum)
//{
// if([[filename pathExtension] isEqualToString:@"jpg"]){
// [files addObject:filename];
// }
//}
NSLog(@"files:%@",files);
//枚举
NSEnumerator *filenum;
filenum = [files objectEnumerator];
while (filename = [filenum nextObject]) {
NSLog(@"filename:%@",filename);
}
一、80386,内存,8255A的连接如图1
图 1
二、编程8255A中断控制器(将ICW写入特定的寄存器)
8255A是可编程中断控制器,对它的设置并不复杂,是通过向相对应的端口写入特定的ICW(Initialization Command Word)来实现的。主8259A对应的端口地址是20h和21h,从8259A对应的端口地址是A0h和A1h。ICW共有4个,每一个都是具有特定格式的字节,为了先对初始化8259A的过程有一个概括的了解,我们过一会再来关注每一个ICW的格式,现在,先来看一下初始化过程:
1、往端口20h(主片)或A0h(从片)写入ICW1。
2、往端口21h(主片)或A1h(从片)写入ICW2。
3、往端口21h(主片)或A1h(从片)写入ICW3。
4、往端口21h(主片)或A1h(从片)写入ICW4。
ICW格式如图2:
图 2 ICW的格式 图 3 OCW1
若想屏蔽或者打开外部中断,只需要往8259A写入OCW1就可以了,即写入中断屏蔽寄存器(IMR),OCW1的格式如图3。
可屏蔽中断与NMI的区别在于是否受到IF位的影响,而8259A的中断屏蔽寄存器(IMR)也影响着中断是否会被响应。所以,外部可屏蔽中断的发生就会受到两个因素的影响,只有当IF位为1,并且IMR相应位为0时才会发生。除单步中断外,所有内部中断都无法禁止,即不能通过CLI指令使IF=0,使其不响应。
三、保护模式下的中断
1、0-19的中断和异常已经安排好了,如书上89页表3.8
2、有特权级变化时,中断堆栈变化如图4。从中断或异常返回时必须使用指令iretd,它和ret很相似,只是它同时会改变eflags的值。需要注意的是,只有当CPL为0时,eflags中的IOPL域才会改变,而且只有当CPL小于等于IOPL时,IF才会被改变。另外,iretd执行时Error Code不会被自动从堆栈弹出,所以执行它之前要先将它从栈中清除掉。指令in、ins、out、outs、cli、sti只有在CPL小于等于IOPL时才能执行。这些指令被称为I/O敏感指令。如果低特权级的指令试图访问这些I/O敏感指令将会导致常规保护错误(#GP)。
图 4 中断或异常发生时的堆栈
3、I/O许可位
TSS偏移102字节处有一个被称做"I/O许可位图基址"的东西,它是一个以TSS的地址为首地址的偏移,指向的便是I/O许可位图。之所以叫做位图,是因为它的每一位表示一个字节的端口地址是否可用。如果某一位为0,则表示此位对应的端口号可用,为1则不可用。由于每一个任务都可以有单独的TSS,所以每个任务可以有它单独的I/O许可位图。
4、保护模式下中断执行过程
以下由硬件自动完成:
①从中断信息中取得中断类型码。
②标志寄存器eflags的值入栈,因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中。
③设置标志寄存器IF和TF位为0,为了防止在此中断中再来其他外部中断。
④cs,eip,error code入栈。
⑤根据中断类型码在IDT中找到中断门执行代码。
IRETD 指令先弹出一个32位的EIP值,然后再弹出一个32位值并将最低的2个字节值传入CS寄存器,最后再弹出一个32位的标志寄存器值。
pmtest9.asm代码如下:
%include "pm.inc" ; 常量, 宏, 以及一些说明 org 07c00h jmp LABEL_BEGIN [SECTION .gdt] ; GDT ; 段基址, 段界限 , 属性 LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符 LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ; Normal 描述符 LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段 LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ; 非一致代码段, 16 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址 ; GDT 结束 GdtLen equ $ - LABEL_GDT ; GDT长度 GdtPtr dw GdtLen - 1 ; GDT界限 dd 0 ; GDT基地址 ; GDT 选择子 SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ; END of [SECTION .gdt] [SECTION .data1] ; 数据段 ALIGN 32 [BITS 32] LABEL_DATA: ; 实模式下使用这些符号 ; 变量 _wSPValueInRealMode dw 0 _SavedIDTR: dd 0 ; 用于保存 IDTR dd 0 _SavedIMREG: db 0 ; 中断屏蔽寄存器值 DataLen equ $ - LABEL_DATA ; END of [SECTION .data1] ; IDT [SECTION .idt] ALIGN 32 [BITS 32] LABEL_IDT:;最多256个中断门,每个占8个字节,所以IDT最大占2K。前面20个已被占用。 ; 门 目标选择子, 偏移, DCount, 属性 %rep 32 Gate SelectorCode32, SpuriousHandler, 0, DA_386IGate %endrep .020h: Gate SelectorCode32, ClockHandler, 0, DA_386IGate ;转换成10进制是32 %rep 95 Gate SelectorCode32, SpuriousHandler, 0, DA_386IGate %endrep .080h: Gate SelectorCode32, UserIntHandler, 0, DA_386IGate ;转换为10进制是128 IdtLen equ $ - LABEL_IDT IdtPtr dw IdtLen - 1 ; 段界限 dd 0 ; 基地址 ; END of [SECTION .idt] [SECTION .s16] [BITS 16] LABEL_BEGIN: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, 0100h mov [LABEL_GO_BACK_TO_REAL+3], ax mov [_wSPValueInRealMode], sp ; 初始化 16 位代码段描述符 mov ax, cs movzx eax, ax shl eax, 4 add eax, LABEL_SEG_CODE16 mov word [LABEL_DESC_CODE16 + 2], ax ;ds:LABEL_DESC_CODE16 shr eax, 16 mov byte [LABEL_DESC_CODE16 + 4], al mov byte [LABEL_DESC_CODE16 + 7], ah ; 初始化 32 位代码段描述符 xor eax, eax mov ax, cs shl eax, 4 add eax, LABEL_SEG_CODE32 mov word [LABEL_DESC_CODE32 + 2], ax shr eax, 16 mov byte [LABEL_DESC_CODE32 + 4], al mov byte [LABEL_DESC_CODE32 + 7], ah ; 为加载 GDTR 作准备 xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_GDT ; eax <- gdt 基地址 mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址 ; 为加载 IDTR 作准备 xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_IDT ; eax <- idt 基地址 mov dword [IdtPtr + 2], eax ; [IdtPtr + 2] <- idt 基地址 ; 保存 IDTR sidt [_SavedIDTR] ;保存IDTR寄存器的值到ds:_SavedIDTR ; 保存中断屏蔽寄存器(IMREG)值 in al, 21h mov [_SavedIMREG], al ; 加载 GDTR lgdt [GdtPtr] ; 关中断 cli ;int 80h可以起作用,但是可屏蔽中断(通过8255设置的)就不能响应了 IF=0 ; 加载 IDTR lidt [IdtPtr] ; 打开地址线A20 in al, 92h or al, 00000010b out 92h, al ; 准备切换到保护模式 mov eax, cr0 or eax, 1 mov cr0, eax ; 真正进入保护模式 jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, ; 并跳转到 Code32Selector:0 处 LABEL_REAL_ENTRY: ; 从保护模式跳回到实模式就到了这里 mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, [_wSPValueInRealMode] lidt [_SavedIDTR] ; 恢复 IDTR 的原值 mov al, [_SavedIMREG] ; ┓恢复中断屏蔽寄存器(IMREG)的原值 out 21h, al ; ┛ in al, 92h ; ┓ and al, 11111101b ; ┣ 关闭 A20 地址线 out 92h, al ; ┛ sti ; 开中断 mov ax, 4c00h ; ┓ int 21h ; ┛回到 DOS ; END of [SECTION .s16] [SECTION .s32]; 32 位代码段. 由实模式跳入. [BITS 32] LABEL_SEG_CODE32: mov ax, SelectorVideo mov gs, ax ; 视频段选择子(目的) call Init8259A int 080h ;内中断,类似调用门 sti ;开中断后,时钟中断开始生效 IF=1 jmp $ ;为了演示结果,去掉后跳回实模式 call SetRealmode8259A ; 到此停止 jmp SelectorCode16:0 ; Init8259A --------------------------------------------------------- Init8259A: mov al, 011hn ;00010001 out 020h, al ; 主8259, ICW1. call io_delay out 0A0h, al ; 从8259, ICW1. call io_delay mov al, 020h ; IRQ0 对应中断向量 0x20 00100000 因为前0-19号中断已经被占了 out 021h, al ; 主8259, ICW2. call io_delay mov al, 028h ; IRQ8 对应中断向量 0x28 00101000 out 0A1h, al ; 从8259, ICW2. call io_delay mov al, 004h ; IR2 对应从8259 00000100 out 021h, al ; 主8259, ICW3. call io_delay mov al, 002h ; 对应主8259的 IR2 0000 0010 out 0A1h, al ; 从8259, ICW3. call io_delay mov al, 001h 0000 0001 out 021h, al ; 主8259, ICW4. call io_delay out 0A1h, al ; 从8259, ICW4. call io_delay ;mov al, 11111111b ; 屏蔽主8259所有中断 mov al, 11111110b ; 仅仅开启定时器中断,外部可屏蔽中断只有在IF=1和IMR对应位为0时才响应 out 021h, al ; 主8259, OCW1. call io_delay mov al, 11111111b ; 屏蔽从8259所有中断 out 0A1h, al ; 从8259, OCW1. call io_delay ret ; Init8259A --------------------------------------------------------- ; SetRealmode8259A --------------------------------------------------------- SetRealmode8259A: mov al, 017h 0001 0111 out 020h, al ; 主8259, ICW1. call io_delay ;4个字节中断向量,单个8259 mov al, 008h ; IRQ0 对应中断向量 0x8 out 021h, al ; 主8259, ICW2. call io_delay ;ICW3已经不需要了 mov al, 001h out 021h, al ; 主8259, ICW4. call io_delay ret ; SetRealmode8259A --------------------------------------------------------- io_delay: nop nop nop nop ret ; int handler --------------------------- _ClockHandler: ClockHandler equ _ClockHandler - $$ inc byte [gs:((80 * 0 + 70) * 2)] ; 屏幕第 0 行, 第 70 列。 mov al, 20h out 20h, al ; 发送 EOI iretd ;IRETD 指令先弹出一个32位的EIP值,然后再弹出一个32位值并将最低的2个字节值传入CS寄存器, ;最后再弹出一个32位的标志寄存器值 _UserIntHandler: UserIntHandler equ _UserIntHandler - $$ mov ah, 0Ch ; 0000: 黑底 1100: 红字 mov al, 'I' mov [gs:((80 * 0 + 70) * 2)], ax ; 屏幕第 0 行, 第 70 列。 iretd _SpuriousHandler: SpuriousHandler equ _SpuriousHandler - $$ mov ah, 0Ch ; 0000: 黑底 1100: 红字 mov al, '!' mov [gs:((80 * 0 + 75) * 2)], ax ; 屏幕第 0 行, 第 75 列。 jmp $ iretd ; --------------------------------------- SegCode32Len equ $ - LABEL_SEG_CODE32 ; END of [SECTION .s32] ; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式 [SECTION .s16code] ALIGN 32 [BITS 16] LABEL_SEG_CODE16: ; 跳回实模式: mov ax, SelectorNormal mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov eax, cr0 and al, 11111110b mov cr0, eax LABEL_GO_BACK_TO_REAL: jmp 0:LABEL_REAL_ENTRY ; 段地址会在程序开始处被设置成正确的值 Code16Len equ $ - LABEL_SEG_CODE16 ; END of [SECTION .s16code]
比如在A页面设置B的delegate为A的实例,
// A.m中某处
B* b = [B alloc] init];
b.delegate = self;
[self.view addSubview:b];
[b release];
那么
1.是A负责创建B的,A的生命周期一定比B要长(B存在,A一定也存在;A存在,B不一定存在)
也就是说 在B(实例b)存在的时候,A(的实例)一定存在, 所以没有必要用retain将引用计数+1,assign足以
2.退一步假设存在这样的情况:A比B先挂掉(A的实例先被release销毁)
那么当然希望是[a relase]后,A中的方法不再被B调用,但是使用retain时候,A还是没有被销毁,所以 A中的方法仍会被B调用,但是assgin就无此问题
3.本质上delegate就是一根指向先于它存在的某个类(CCClass)的指针(假设是:ccPoint),我们通过delegate这根指针去指向这个已经存在的指针(ccPoint) 那么通过delegate即ccPoint也就可以访问CCClass中的实例方法