[精通Objective-C] 使用自定义下标模拟32位计算机寄存器操作
2016-07-15 16:02
337 查看
[精通Objective-C] 使用自定义下标模拟32位计算机寄存器操作
参考书籍:《精通Objective-C》【美】 Keith Lee目录
精通Objective-C 使用自定义下标模拟32位计算机寄存器操作目录
程序功能简介
寄存器类
命令行解析类
测试
程序功能简介
创建一个命令行程序用于模拟32位计算机的寄存器操作。它可以设置和获取寄存器的内容。该程序含有3个命令行输入参数:寄存器的初始化设置(32位的十六进制值)、选中的用于执行获取/设置操作的寄存器字节,以及(可选的)用于设置的寄存器字节值(十六进制)。寄存器类
首先创建一个用于存放寄存器常量的头文件RegEditConstants.h#ifndef RegEditConstants_h #define RegEditConstants_h #define kByteMultiplier 0xFF // 用于辅助执行寄存器的位操作 #define kRegisterSize (sizeof(uint32)) // 寄存器的宽度(以位为单位) #endif
接下来是模拟寄存器操作的RegEdit类:
#import <Foundation/Foundation.h> @interface RegEdit : NSObject @property(readonly) uint32 regSetting; -(id) initWithValue:(uint32)value; // 实现数组型自定义下标必须实现的两个方法 -(id) objectAtIndexedSubscript:(NSInteger)index; -(void) setObject:(id)newValue atIndexedSubscript:(NSUInteger)index; @end
#import "RegEdit.h" #import "RegEditConstants.h" @interface RegEdit() @property(readwrite) uint32 regSetting; @end @implementation RegEdit // 寄存器的初始化设置 -(id) initWithValue:(uint32)value{ if ((self = [super init])) { _regSetting = value; } return self; } // 读寄存器操作,操作单位为1个字节(8位) -(id) objectAtIndexedSubscript:(NSInteger)index{ NSUInteger byteNumber = index * 8; if ((1 << byteNumber) > self.regSetting) { [NSException raise:NSRangeException format:@"Byte selected(%ld) exceeds number value", index]; } unsigned int byteValue = (self.regSetting & (kByteMultiplier << byteNumber)) >> byteNumber; return [NSNumber numberWithUnsignedInt:byteValue]; } // 写寄存器操作,操作单位为1个字节(8位) -(void) setObject:(id)newValue atIndexedSubscript:(NSUInteger)index{ if (newValue == nil) { [NSException raise:NSInvalidArgumentException format:@"New value is nil"]; } NSUInteger byteNumber = index * 8; if ((1 << byteNumber) > self.regSetting) { [NSException raise:NSRangeException format:@"Byte selected(%ld) exceeds number value", index]; } uint32 mask = ~(kByteMultiplier << byteNumber); uint32 tmpValue = self.regSetting & mask; unsigned char newByte = [newValue unsignedIntegerValue]; self.regSetting = (newByte << byteNumber) | tmpValue; } @end
命令行解析类
用于解析命令行并判断其有效性的CLIParser类。#import <Foundation/Foundation.h> @interface CLIParser : NSObject -(id) initWithCount:(int)argc arguments:(const char *[])argv; -(BOOL) parseWithRegister:(uint32 *)registerValue byteNumber:(NSInteger *)byteN doSetByte:(BOOL *)doSet byteValue:(unsigned int *)byteValue error:(NSError **)anError; @end
#import "CLIParser.h" #import "RegEditConstants.h" NSString *HelpCommand = @"\n RegEdit -n [Hex initial register settings] -b [byte number] -v [hex byte value]"; NSString *HelpDesc = @"\n\nName\n RegEdit - Get/set selected byte of a register"; NSString *HelpSynopsis = @"\n\nSYNOPSIS"; NSString *HelpOptions = @"\n\nOPTIONS"; NSString *HelpRegValue = @"\n -n\tThe initial register settings."; NSString *HelpRegByte = @"\n -b\tThe byte to retrieve from the register."; NSString *HelpByteValue = @"\n -v\tValue to set for the selected register byte."; @implementation CLIParser { const char **argValues; int argCount; } // 接收传入参数 -(id) initWithCount:(int)argc arguments:(const char *[])argv{ if ((self = [super init])) { argCount = argc; argValues = argv; } return self; } // 判断命令行语句的合法性 -(BOOL) parseWithRegister:(uint32 *)registerValue byteNumber:(NSInteger *)byteN doSetByte:(BOOL *)doSet byteValue:(unsigned int *)byteValue error:(NSError *__autoreleasing *)anError{ // 使用NSUserDefaults类获取命令行参数 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *numberString = [defaults stringForKey:@"n"]; NSString *byteString = [defaults stringForKey:@"b"]; NSString *valueString = [defaults stringForKey:@"v"]; // 如果用户没用提供寄存器值或字节数,就显示帮助信息 if (!numberString || !byteString) { NSString *help = [NSString stringWithFormat:@"%@%@%@%@%@%@%@",HelpDesc,HelpSynopsis,HelpCommand,HelpOptions,HelpRegValue,HelpRegByte,HelpByteValue]; printf("%s\n", [help UTF8String]); return NO; } // 检查输入的寄存器值 NSScanner *scanner = [NSScanner scannerWithString:numberString]; // scanHexInt:方法返回值为是否从NSString对象中找到有效的十六进制整数 if (!numberString || ([numberString length] == 0) || ([numberString length] > kRegisterSize * 2) || ![scanner scanHexInt:registerValue]) { if(anError != NULL){ NSString *msg = [NSString stringWithFormat:@"ERROR!, Register value must be from 1-%ld hexadecimal characters", kRegisterSize * 2]; NSString *description = NSLocalizedString(msg, @""); NSDictionary *info = @{NSLocalizedDescriptionKey:description}; int errorCode = 1; *anError = [NSError errorWithDomain:@"CustomErrorDomain" code:errorCode userInfo:info]; } return NO; } // 检查输入的寄存器字节数 scanner = [NSScanner scannerWithString:byteString]; if (!byteString || ([byteString length] == 0) || [scanner scanInteger:byteN]) { unsigned int numberLength = (unsigned int)(ceil([numberString length] * 0.5)); if ((*byteN < 0) || (*byteN > (numberLength - 1))) { if (anError != NULL) { NSString *msg = [NSString stringWithFormat:@"ERROR!, Register byte number must be from 0-%d", numberLength - 1]; NSString *description = NSLocalizedString(msg, @""); NSDictionary *info = @{NSLocalizedDescriptionKey:description}; int errorCode = 2; *anError = [NSError errorWithDomain:@"CustomErrorDomain" code:errorCode userInfo:info]; } return NO; } } // 检查用于设置寄存器字节内容的输入值 if (valueString) { // 写操作标识符设为真 *doSet = YES; scanner = [NSScanner scannerWithString:valueString]; if([scanner scanHexInt:byteValue]){ if (*byteValue > UCHAR_MAX) { if (anError != NULL) { NSString *msg = [NSString stringWithFormat:@"ERROR!, Register byte value must be 1-2 hexadecimal characters"]; NSString *description = NSLocalizedString(msg, @""); NSDictionary *info = @{NSLocalizedDescriptionKey:description}; int errorCode = 3; *anError = [NSError errorWithDomain:@"CustomErrorDomain" code:errorCode userInfo:info]; } return NO; } } } return YES; } @end
测试
首先设置运行程序时传递的参数点击下图中标记处,选择Edit Scheme:
在弹出窗口的下图标记位置输入命令行参数 “-n 1FB2C3A6 -b 0 -v A5”(可自定义)
最后在main.m中进行测试:
#import <Foundation/Foundation.h> #import "RegEdit.h" #import "CLIParser.h" int main(int argc, const char * argv[]) { @autoreleasepool { // 使用CLIParser对象获取命令行参数 CLIParser *parser = [[CLIParser alloc] initWithCount:argc arguments:argv]; uint32 registerValue; NSInteger registerByte; unsigned int byteValue; BOOL isSetByte; NSError *error; BOOL success = [parser parseWithRegister:®isterValue byteNumber:®isterByte doSetByte:&isSetByte byteValue:&byteValue error:&error]; if (!success) { // 将错误记录到日志中并退出 if (error) { NSLog(@"%@",[error localizedDescription]); return -1; } } else{ // 创建一个RegEdit对象并设置它的初始值 RegEdit *regEdit = [[RegEdit alloc] initWithValue:registerValue]; NSLog(@"Initial register settings -> 0x%X", (uint32)[regEdit regSetting]); // 使用自定义下标获取选中的寄存器字节 NSNumber *byte = regEdit[registerByte]; NSLog(@"Byte %ld value retrieved -> 0x%X", (long)registerByte, [byte intValue]); // 使用自定义下标将选中的寄存器字节的内容设置为输入值 if (isSetByte) { NSLog(@"Setting byte %d value to -> 0x%X",(int)registerByte, byteValue); regEdit[registerByte] = [NSNumber numberWithUnsignedInteger:byteValue]; NSLog(@"Updated register settings -> 0x%X", [regEdit regSetting]); } } } return 0; }
运行结果:
2016-07-15 14:58:45.206 RegEdit[16984:163010] Initial register settings -> 0x1FB2C3A6 2016-07-15 14:58:45.207 RegEdit[16984:163010] Byte 0 value retrieved -> 0xA6 2016-07-15 14:58:45.207 RegEdit[16984:163010] Setting byte 0 value to -> 0xA5 2016-07-15 14:58:45.207 RegEdit[16984:163010] Updated register settings -> 0x1FB2C3A5
可以看到寄存器字节为0的值由十六进驻数A6修改成了十六进制数A5。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- PHP 命令行参数详解及应用
- bash shell命令行选项与修传入参数处理
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结
- iOS应用中UISearchDisplayController搜索效果的用法
- iOS App开发中的UISegmentedControl分段组件用法总结
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- iOS中UIAlertView警告框组件的使用教程
- 浅析iOS应用开发中线程间的通信与线程安全问题
- python 获取命令行参数 函数