我编写了一些代码来将补丁应用于二进制文件,补丁分隔为十六进制值的ascii表示,如下所示:00FF00:A155F3; 9210BC。
我的问题是我错误地计算十六进制的值恰好是256,但只是在分隔符':'和';'之间因为无论代码中的位置如何,我使用相同的hex2char()函数,我无法弄清楚为什么它在这个特定区域失败了。我想,而不是浪费太多时间,我会注册stackoverflow并获得一些帮助。
我不想使用任何外部库,我不想包含除stdio.h和stdlib.h之外的任何内容(我将删除sys / stat.h,以及fread()和realloc()直到EOF,但这是另一个问题,我并不关心它)
这是代码,我的主循环接近结束,我清楚地标记了我得到错误输出的地方:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
//I'll populate this later
struct _pos {
unsigned pos;
} pos;
//raise x to the power of y
unsigned power( unsigned x, unsigned y )
{
if ( y == 0 )
{
return 1;
}
else
{
return x * power( x, y - 1 );
}
}
//convert ascii hex values to integers
unsigned h2i(const char *input, int len) {
unsigned retval = 0;
char cur = 0;
int loops = 0;
while (0 < len) {
cur = input[--len];
//check if we are out of the range hex would be in
//we assume capital letters A - F
if ( cur < 0x30 || cur > 0x46 ) {
printf("Hex out of range: %X\n", cur);
exit(EXIT_FAILURE);
}
//numerical
if ( cur < 0x3a ) {
cur -= 0x30;
}
//alphabetical
else {
cur -= 0x37;
}
retval += (cur * power(16, loops));
++loops;
}
return retval;
}
//take 2 chars from the input and get a hex value from it
char hex2char(const char *input) {
char buff[2];
buff[0] = input[pos.pos++];
buff[1] = input[pos.pos++];
printf("\nBUFF: %c%c : POS: %i\n", buff[0], buff[1], pos.pos);
return h2i(buff, 2);
}
//turn a delimiter terminated string into a number
unsigned hex2int(const char *input, char delimiter) {
int offset = 0;
char buff[13]; //max int length if represented by string
//copy string into the buffer
while (input[offset] != delimiter) {
if (offset == 12) {
printf("parse error: offset\n");
exit(EXIT_FAILURE);
}
buff[offset] = input[offset];
++offset;
}
//printf("BUFF: %s : OFFSET: %i\n", buff, offset);
pos.pos += offset;
return h2i(buff, offset);
}
char *fast_cache( char *Filename, unsigned long *size ) {
FILE *FilePointer;
FilePointer = fopen( Filename, "r" );
if ( FilePointer != NULL ) {
char *ptr;
struct stat FileStat;
fstat( fileno( FilePointer ), &FileStat );
*size = FileStat.st_size;
ptr = ( char * ) malloc( *size );
fread( ptr, 1, *size, FilePointer );
fclose( FilePointer );
return ptr;
}
else {
return NULL;
}
}
int main(int argc, char **argv)
{
// print greeting
printf("Hello World!\n");
unsigned long size;
char *file = fast_cache(argv[1], &size);
if (file == NULL) {
printf("You must specify an input!\n");
exit(EXIT_FAILURE);
}
//okay, patchfile found, opened, and cached, time to convert
pos.pos = 0; //file position
//this will be the output, unused right now
FILE *out = fopen("output", "w");
//a line in the file is formatted like this
//0000FF:A9DF23;A7FF11
unsigned fileoffset = 0;
unsigned trash = 0;
//loop through all lines in the patchfile
while (pos.pos < size) {
fileoffset = hex2int(file, 0x3a);
++pos.pos;
printf("offset: %u CUR: %c\n", fileoffset, file[pos.pos]);
while(file[pos.pos] != 0x3b ) {
//check current values with file values
//not implimented yet, i just print it out
///////////////////////////////////////////////////////////////////
///////////This is the issue right here///////////////////////////
//printf prints a near MAX_INT number hex value > 0xFFFFFF00
//and it is off by exactly 256 every time, but that would mean overflowing
printf("%X ", hex2char(file));
}
//////////////////////////////////////////////////////////////////
//but right here until EOF, everything is fine and works normally
//and it's the same freaking function
printf("\nfound delimiter: %c @ %u\n", file[pos.pos], pos.pos);
++pos.pos;
//second half of the line
while(file[pos.pos] != '\n' && pos.pos < size) {
printf("%X ", hex2char(file));
}
//eat the new line if there is one
++pos.pos;
printf("\nLine complete\n");
}
return 0;
}
答案 0 :(得分:3)
在C中使用printf时,您的字符将被提升为整数。由于它们是无符号字符,因此必须屏蔽剩余的字符。
替换:
printf("%X ", hex2char(file));
使用:
printf("%X ", hex2char(file) & 0xff);
您可以在此处找到此问题的完整说明: Printing hexadecimal characters in C 在这里http://en.wikipedia.org/wiki/Sign_extension
如果你必须在装配中实现这一点,我建议通过简单的位移操作来替换你的pow功能。 X <&lt; 4 == X * 16.还要注意在微控制器或其他嵌入式系统上,你可以找到一个16位系统。在这种情况下,int的大小可以不同。
答案 1 :(得分:2)
将字符串转换为整数的代码实际上是非常复杂的。
当你需要的是像power()
这样的函数来将值向左移动4位时,涉及x <<= 4
之类的(递归!)函数真是太过分了。
在代码中没有详细说明,尝试将十六进制字符串替换为整数函数,例如:
/* Parse hexadecimal number at s into value stored in v. Returns pointer to first
* character that is not part of the number. Doesn't protect against overflow.
*/
const char * parse_int_hex(const char *s, unsigned long *v)
{
*v = 0;
for(; ; s++ )
{
char here = *s;
unsigned long dv;
if( here >= '0' && here <= '9' )
dv = here - '0';
else if( here >= 'a' && here <= 'f' )
dv = 10 + here - 'a';
else if( here >= 'A' && here <= 'F' )
dv = 10 + here - 'A';
else
return s;
*v <<= 4;
*v += dv;
}
return s;
}
上面没有依赖关系,这就是字符检查如此繁琐的原因。 :)这是关于普通的十六进制到整数转换例程所期望的大小。