用C语言开发查看HEX字节码的工具--看程序如何进化

昨日所作的查看HEX字节码程序,虽然不完善,但代码量的确很小。其中核心代码不过十行上下,其余还都是例行公事,如打开文件,检查输入命令并跳转执行的。

现在,我再增加数行代码,使之在界面和功能上接近UltraEdit或Notepad++的显示,甚至更强!对于4GB的大文件(如电影、视频、光盘ISO映像文件等) 都可秒开,并跳转到任意位置查看,且并未多占内存!

可能吗?当然,不过是命令行程序最简单的技巧了。昨日所作程序(https://blog.csdn.net/shaoyubin999/article/details/82950806 )就能查看大文件,其实,所以谓打开文件,不过是指针指向它,并未调入内存!当需要显示哪部分,再将文件指针偏到那里,再读入少量内容即可。

先看看操作和功能

使用手册

任何软件都应有一个使用说明手册或帮助文档。Unix/Linux风格的手册通常以MarkDown格式和man格式写成,其实就是TXT文本。我们极力不推荐使用DOC格式!

这个小软件只需简单操作说明即可。文本(bin2hexReadme.txt)如下:

bin2hex V1.0
一个二进制文件查看程序
http://www.wtclab.net 2018 Copyleft(L)
功能:
查看二进制文件的内容,十六进制HEX数和对应的可显示字符表示。
查看当前键盘输入键的ASCII码。例如键入 ? 显示 ASCII为63
command $ ? (ASCII 63)
用法:
在命令提示符$下,
(1)向上翻页: 用上箭头↑、减号键 - 、[ 都可
(2)向下翻页: 用下箭头↓、加号(等号)=、] 、空格键Space、回车都可。
(3)回到文件头部:h键
(4)到文件结束部:e键
(5)从任意位置查看:j键,然后输入查看位置的十六进制地址
(6)进入安静模式:n键
(7)退出安静模式,回到普通命令模式:ESC键
(8)退出: q键或 Ctrl+c
(9)是否在字串中显示ASCII值高于127的,如汉字等? 用 p 键来回切换。
(10)显示本帮助:用 ? 键
(11)改变显示界面颜色:k 黑底白字 w 白背景黑字 b 蓝底白字 y 黑底黄字 g 黑底绿字
示例 command $ ? (ASCII 63)【这里显示上次键入的键及键值】
command $

使用界面

接下来,看看使用界面,为对比,我也以UltraEdit和Notepad++打开同样的二进制文件(注意,太大的文件这两款编辑器都打不开,所以先用小文件测试,这两款软件打开50M以内的文件都还行)。

找一个任意文件,这里我还是用123.rar作测试文件。

bin2hex 123.rar

结果:

UltraEdit的打开结果:
在这里插入图片描述

Notepad++的结果:
在这里插入图片描述

对比一下三个软件在处理字节串ASCII显示时的不同,由于ASCII码值在32到127内是可显示的,127以上通常用作不同编码模式的字符,如各种编码模式的下汉字,所以只能显示成“乱码”了。

在这里插入图片描述

换肤

从对比上看,我的软件显示也不错。我的软件轻易换肤

命令行窗口颜色是可变换的,在windows下用color命令即可,只是少有人用罢。我在软件中集成了一些色彩,作为控制示例。如,键入k,w,b,y,g等可改变显示界面颜色:

  • k 黑底白字
  • w 白背景黑字
  • b 蓝底白字
  • y 黑底黄字
  • g 黑底绿字

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

帮助系统

随时键入 ?即可见帮助。帮助也就是打出文本 bin2hexReadme.txt 。

在这里插入图片描述

退出

命令行给出了提示,键入q则退出, 这也是大多数命令行程序通用的做法(如MATLAB 支持Exit和Quit退出)。 为了兼容用户习惯,我还默认用Ctrl+c也可退出。

导航

我设置了多种导航(上下翻页)键可用,都是常用软件所默认的,如以输入法类似的翻页模式:加减号键、左右方括号键、又如用上下箭头翻页键。特别地,以空格键和回车都作为了向下翻页,这也符合通常用户习惯。

注意,软件操作设计最要不得的就是标新立异,符合常用默认操作,则软件的免学习的。

我用了h键回到文件头,h是home的意思。用e键直接到文件尾,e是end的意思,当然还可以设置其他任何导航方式。这里设置只是为了示例在代码中如何实现。

用j (Jump)则可输入任意想查看的文件字节地址。如j2345则跳到0x00002345的位置,如图:
在这里插入图片描述

特有功能

如果嫌字符串中显示乱码汉字不美,也可选择纯ASCII模式。键入p (代表 pure)即可,如图:
在这里插入图片描述

p 是开关键, 再次键入 p 则回到常规显示。

软件每次完成任务后,都在下方提示命令输入,顺便也将上次键入的字符及其ASCII码显示出来。因此,软件也可当一个简单的ASCII码查寻器用。提示命令输入也可MATLAB、Python、Julia、MySQL、Gnuplot等等软件通行的做法。

在这里插入图片描述

UNIX和LINUX提倡 沉默是金。如果嫌总是发现命令提示,也可进入安静模式:只要键入n即可。用ESC即退回命令模式。进入安静模式前,还作了提示,如何退回命令模式。

在这里插入图片描述
安静模式下一切命令均可用,如导航,跳转j,换肤(k,w,b,y,g),显示开关p, 帮助?、退出q等等。程序中,新加命令无非是加条件切换操作罢了。编程不难。

安静模式的界面极为纯净。

在这里插入图片描述

打开巨大文件测试

我打开一个ISO文件。
在这里插入图片描述

可用j 命令瞬间跳到任意位置。

在这里插入图片描述

代码共182行

以上功能实现的代码却不多。保持简洁,才是王道。新版的 bin2hex.c含注释共182行。尚可再简。用tcc, gcc或 VC 6.0编译都通过。TCC编译指令是:

tcc bin2hex.c -o bin2hex.exe

团队同学可用JAVA或其他语言重写之。

【bin2hex.c】

//bin2hex.c
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main(int argc, char *argv[])
{
  unsigned char c,ch[17];//记录单字符,ch记录一行字节内容
  const int len=16*16;//每次输出长度16行,每行16字节
  int i,k,j;//记录长度,i循环变量,k用于ch[k]的脚标,j循环变量
  int commandchar=0;//命令字
  long addr;//地址偏移量
  int nomessages=0;//为1则启用安静模式
  int pure=0;//pure=1时字节串中不显示乱码汉字(即高于127或低于32的ASCII码显示为句点)
  long tmpint;//记录文件尾位置备用
  FILE *fp;
  if(argc<2)
    {
      printf("Show HEX code of anyfile  2018 WTCLAB.NET CopyLeft (L)\n");
      printf("Usage: bin2hex anyfilename");
      return 0;
    }
  system("chcp 936");//windows中文码页
  fp=fopen(argv[1],"rb");
  if(fp==NULL)
    {
      printf("file %s not found\n",argv[1]);
      return 0;
    }
  system("color f0"); //改变窗口默认为白底黑字
  while(1) //打印二进数据内容表
    {    
      if(nomessages==0)//输出标准模式消息
        {
          printf("\n Address | 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |");
          if(pure==1){printf("Dump [pure display] \n");}
          else{printf("        Dump   \n");}
          printf("---------|------------------------------------------------|");
          printf("-------------------");
        }
      for(i=0; i<len; i++)//输出len个字节,16个为一行
        {
          fread(&c,1,1,fp);
          
          if(feof(fp)!=0)
            {
              tmpint=16-ftell(fp)%16;//求余对齐
              for(j=0; j<3*tmpint; j++)putc(0x20, stdout);  //3个空格
              ch[16-tmpint]='\0';//字串到【16-tmpint】位置结束
              printf("|  %s",ch);//输出”乱码字串“
              break; //读到文件尾就结束
            }

          if(i%16 == 0)
            {
              k=0;
              printf("\n %08x|",ftell(fp)-1); //换行输出地址
            }
          printf("%02x ",c);//按16进制输出读入的字节值
         
          c=(c<32 |c==0xff)? 46: c;//46为ASCII码句点,将非打印码处理为句点显示
          c=(pure==1 & c>127)? 46:c; //这样就不显示汉字,改显46
          ch[k]=c; 
          k++;//记录1行字符以备输出
          if(k==16)//输出一行对应的ASCII串,if((i+1)%16 == 0)
            {
              ch[16]='\0';
              printf("|  %s",ch);//输出”乱码字串“
            }
        }
      if(nomessages==0)//输出标准模式消息
        {
          printf("\n[tips]:prev/next:[\xa1\xfc/- \xa1\xfd/=] \
h(home) e(end) j(jump)  q(quit) \n");//输出命令提示,\xa1\xfc为上箭头
          printf("       n(silent mode) w,k,g,b,y(disp. color) ESC(command mode)\
 \n       p(pure ASCII disp.)  ?(for help) ");
 
          if(commandchar<32){
              c=32; //处理不能打印的ASCII
            }
          else{
              c=commandchar;
            }
          printf("\n command $  %c (ASCII %d)",c,commandchar);
          //输出键盘消息字符和对应的ASCII值
          printf("\n command $ ");
        }//输出安静模式消息

      commandchar=getch();//接收控制命令并执行
      if(commandchar=='q' |commandchar=='\x3' )break; //退出: q键或 Ctrl+c
      if(commandchar=='[' | commandchar==72 |commandchar==45)//键盘[或上箭头或减号
        {         
          if(ftell(fp)>(1*16)*16)
            {
              tmpint=ftell(fp);
              tmpint=tmpint-16*(tmpint/16);//求余对齐
              fseek(fp,-(2*16)*16-tmpint,1);//指针回卷32行,到上一屏位置
            }
          else
            {
              //如果到达文件头则不动作
              rewind(fp);//指针回文件头
            }
        }
      else if(commandchar==']' | commandchar==80 | commandchar==32\
              |commandchar==13 |commandchar==61)
        {
          //键盘]或下箭头80或空格32或回车13或加号(等号)61
          //直接到下一屏位置。即fseek(fp,0,1);但到文件结束处要处理对齐
          tmpint=ftell(fp);
          tmpint=tmpint-16*(tmpint/16);//求余对齐
          fseek(fp,-tmpint,1);//对齐
        }
      else if(commandchar=='h')//键盘s:回文件头
        {
          system("cls");
          rewind(fp);
        }
      else if(commandchar=='e')//键盘e:至文件尾
        {
          fseek(fp,0,2);//移到文尾
          tmpint=ftell(fp);//读尾部指针
          tmpint=tmpint-16*(tmpint/16);//求余,对齐
          fseek(fp,-15*16-tmpint,2);//到文件尾,回溯16行输出
        }
      else if(commandchar=='j')//键盘j:输入开始行地址
        {
          printf("\naddress(HEX)? Example:0x1024 > 0x");
          scanf("%x",&addr);
          addr=16*(addr/16);//从16的整数倍开始
          fseek(fp,addr,0);
        }
      else if(commandchar=='n')//键盘n:静默模式:不显示提示
        {
          nomessages=1;
          printf("\n Silence Mode now!\nESC return to normal mode,Any key to go!");
          getch();
        }
      else if(commandchar==27)//键盘ESC:回到显示提示模式
        {
          nomessages=0;
          fseek(fp,-16*16,1); //显示不动:回16行重打出来
        }
      else if(commandchar=='k')//显示背景色彩:黑底白字
        {
          system("color 0f");fseek(fp,-16*16,1);
        }
      else if(commandchar=='w')//显示背景色彩:白底黑字
        {
          system("color f0");fseek(fp,-16*16,1);
        }
      else if(commandchar=='y')//显示背景色彩:黑底黄字
        {
          system("color 0e");fseek(fp,-16*16,1);
        }
      else if(commandchar=='b')//显示背景色彩:蓝底白字
        {
          system("color 1f");fseek(fp,-16*16,1);
        } 
      else if(commandchar=='g')//显示背景色彩:黑底绿字
        {
          system("color 0a");fseek(fp,-16*16,1);
        }        
      else if(commandchar=='?')//显示帮助
        {
          system("type bin2hexReadme.txt");
          fseek(fp,-16*16,1);
          system("pause");
        }
      else if(commandchar=='p')//显示字串模式切换
        {   
          pure=(pure!=0)? 0:1; //或pure=(pure+1)%2; //
          fseek(fp,-16*16,1); //显示不动:回16行重打出来
        }
      else
        {
          fseek(fp,-16*16,1); //其他键:显示不动:回16行重打出来
        }
    }
  fclose(fp);
  system("color 07");
  return 0;
}

帮助文档
【bin2hexReadme.txt】

bin2hex  V1.0
         一个二进制文件查看程序 
         http://www.wtclab.net 2018 Copyleft(L)       
功能:
     查看二进制文件的内容,十六进制HEX数和对应的可显示字符表示。
     查看当前键盘输入键的ASCII码。例如键入 ? 显示 ASCII为63
     command $  ? (ASCII 63)    
用法: 
     在命令提示符$下,
(1)向上翻页: 用上箭头↑、减号键 - 、[ 都可
(2)向下翻页: 用下箭头↓、加号(等号)=、] 、空格键Space、回车都可。
(3)回到文件头部:h键
(4)到文件结束部:e键
(5)从任意位置查看:j键,然后输入查看位置的十六进制地址
(6)进入安静模式:n键   
(7)退出安静模式,回到普通命令模式:ESC键
(8)退出: q键或 Ctrl+c
(9)是否在字串中显示ASCII值高于127的,如汉字等? 用 p 键来回切换。
(10)显示本帮助:用 ? 键
(11)改变显示界面颜色:k 黑底白字 w 白背景黑字 b 蓝底白字  y 黑底黄字 g 黑底绿字 
示例    command $  ? (ASCII 63)【这里显示上次键入的键及键值】
        command $ 
 

源码及编译结果下载点:

https://pan.baidu.com/s/18qlbviVugrr6SmlstnQBIw

已知BUG和不足

程序毕竟是人编的,总是存在不足点,需要不断改进。程序完成后应做完整测试。目前,作为示例,我故意在测试后未进改代码。其实,能发现错误,才能有改进的思路。

BUG

  • j命令后如果输入不是十六进制数字字符,将出错,你不能期望软件用户都依照程序员的设计来操作。这一点需要对输入进行合法性检查或过滤。
  • bin2hex.exe与当前工作路径不一致时,将导致帮助文件打开失败。这是帮助文档写在外部的不利处。进一步可用exe文件路径检测方法来解决(在windows.h中用GetModuleFileName函数即可)。但这样一来就不能跨平台了,所以不是最佳。

不足

暂列为2点:

  • 还没有快进/快退操作。
  • 没有显示当前位置的进度百分比。
  • 随着软件功能增加,需改进程序总的结构以适应。

改进的方向

软件结构上,还有可改进的地方:

  • 代码中我用了常规的if-else语句进行输入控制分支,实际上,这里用case语句更简单。
  • 输入命令如果多了,代码在结构上就显冗杂。可考虑将输入操作做成一个函数代码,又将输出显示作为另一函数代码,在主程序中使用。这属于程序优化的过程。当程序基本功能完成并不断增加附加功能和完善时,代码量会增大,原来求简的结构会逐渐不适应,这时就要考虑以封装(也就是包装为函数和通过函数做数据接口)来增补结构。所以程序是一个不断进化的过程,不要在一开始就去考虑所谓“ 完善的” 接口和架构!就象一个小公司,成立之初,重为生存,简则有效,等成长到一定规模,再考虑扩展各种机构。你见过街边小吃店里有财务部、人事部?如果真有,就是这家小店的主人不懂人事了。始终注意,小而精巧,是C语言区别于JAVA、C++最著名的特征。但这不意味着用C碰能做大程序,C的设计理念是,在代码的进化中成长,象昆虫那样,该蜕皮时才蜕皮。
  • 使终记住,改进是为了更简单。更易于后期维护。在一定程度上,封装是一把双刃剑,要用,但要慎用。软件包裹的层数越多,外表上看上去会越简洁,但不意味着就越简明
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
hexeditor-0.9.12-x64.zip是一个用于查看和编辑二进制文件工具软件。该软件的命名中,"hexeditor"表示该软件是一个十六进制编辑器;"0.9.12"表示该软件的版本号为0.9.12;"x64"表示该软件适用于64位操作系统。 十六进制编辑器主要用于查看和修改计算机中的二进制数据。二进制数据是计算机中各种文件和信息的基本形式,如可执行文件、图片、音频和视频文件等。通常情况下,二进制数据是以十六进制形式呈现的,即每个字节由两个十六进制数字表示。 hexeditor-0.9.12-x64.zip提供了一个直观的界面,让用户可以方便地查看和修改二进制文件的内容。用户可以选择打开所需的二进制文件,并以十六进制形式显示其中的数据。该编辑器还提供了一些常用的编辑功能,如复制、粘贴和搜索等。用户可以通过这些功能,直接在二进制数据中进行相应操作。 使用hexeditor-0.9.12-x64.zip,用户可以进行各种操作,例如修改可执行文件的指令,编辑图片文件的像素数据,或者调整音频文件的音频流等。同时,该软件还提供了一些高级功能,如数据搜索和替换、查找差异等。这些功能对于计算机专业人员来说,尤其有用,可以帮助他们识别和解决二进制数据中的问题。 总之,hexeditor-0.9.12-x64.zip是一个功能丰富的十六进制编辑器软件,适用于64位操作系统。它能够方便地查看和编辑二进制文件,减轻了计算机专业人员在处理二进制数据时的工作负担。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值