od
(octaldump) 명령은 Unix 버전 1부터 구현됩니다. 하지만 나는버전 6 유닉스 매뉴얼(1975).현대적인 방법od
or 를 사용한 xxd
리버스 엔지니어링은 sed
Unix V6에서 작동하지 않습니다. 왜냐하면 sed
and는 awk
버전 7에서만 나타나기 때문입니다(and uudecode
, xxd
및 base64
도 사용할 수 없습니다).
문제는 다음과 같습니다
- 1975년에 사람들은 어떻게 8진수 또는 16진수 목록을 이진수로 변환했습니까?
- 클립보드의 텍스트만 터미널에 붙여넣을 수 있는 PDP-11 에뮬레이터에서 이 작업을 어떻게 수행합니까? (즉, 이를 위해 자체 프로그램을 작성해야 합니까?)
od
다음은 바이너리 파일로 다시 변환하려는 바이너리 파일의 16진수 덤프 예입니다 .
# od -h /bin/sum
0000000 0107 00ba 0000 0204 0000 0000 0000 0001
0000020 1583 0bd6 0ac3 0601 8901 0a37 00ae 15b7
0000040 0002 8905 0000 0000 8609 15c0 0001 8904
0000060 0026 0005 01ef 706f 6472 000a 1001 0a05
0000100 1040 8903 00be 0200 870b 0bc0 030e 0ab7
0000120 007a 15c2 00be 9484 6105 0b45 7e04 01f0
0000140 15c0 0001 8904 0080 0002 09f7 0026 15c0
0000160 0001 8904 0083 0001 1dc5 0050 09f7 0014
0000200 15c0 0001 8904 0082 0001 1040 8906 01c2
0000220 203f 200a 1026 1066 1141 09f7 0006 1581
0000240 1580 0087 0a00 7217 000a 1066 1001 0302
0000260 09f7 fff0 15b7 0012 65f7 0030 000c 15c0
0000300 0001 8904 00ba 0001 0087
0000312
답변1
Unix 버전 6 에는 버전 7에만 있었던 일반 도구(예: sed
및 )가 많이 포함되어 있지 않은 것으로 보입니다 awk
. 당시 Unix는 아직 상용화되지 않았으므로 단순히 해당 작업에 대한 수요가 널리 퍼지지 않았거나 Ken(또는 다른 프로그래머)이 /usr
Bell Labs에서 가져왔기 때문에 "역 16진수 덤프"가 손실되었을 수 있습니다. 비공식 디렉토리에서 사용 가능합니다. 누가 알아.
하지만 여기 Unix V6에서 16진수 덤프를 되돌리는 구현이 있습니다. 처럼 컴파일하면 cc -s -O unhex.c
결과 실행 파일은 1160바이트에 불과하고 (예상대로) 덤프보다 빠르게 실행됩니다.
당시 C 언어에는 여전히 B의 복합 할당 구문( =+
, =*
등)이 있었고 프로그래머가 파일 I/O를 위해 자체 버퍼를 제공해야 한다는 점에 유의하세요.
/* reverse "od -h" operation on Unix V6 */
/* written in pre-K&R C */
/* derived from wc.c and cvopt.c */
int ibuf[259];
int obuf[259];
main(argc,argv)
char **argv;
{
int token, bytecnt;
register char *p1, *p2; /* input buffer pointers */
register int c; /* char or read count */
char sp, b1, b2, lastc, lastb2, nfirst;
obuf[0] = 1; /* standard output by default */
if (argc>2) {
/* create output file */
if ((obuf[0] = creat(argv[2], 0666)) < 0) {
diag(argv[2]);
diag(": failed to create\n");
return;
}
}
if (argc>1 && fopen(argv[1], ibuf)>=0) {
p1 = 0;
p2 = 0;
sp = 0;
token = 0;
bytecnt = 0;
nfirst = 0;
for(;;) {
/* reading from file */
if (p1 >= p2) {
p1 = &ibuf[1];
c = read(ibuf[0], p1, 512);
if (c <= 0)
break;
p2 = p1+c;
}
/* decoding loop */
c = 0;
c =| *p1++;
if (c==' ' || c=='\n') {
b1 = token;
b2 = token >> 8;
if (lastc!=' ' && lastc!='\n') {
/* end of token */
if (sp>0) {
if (nfirst) putc(lastb2, obuf);
putc(b1, obuf);
lastb2 = b2;
nfirst = 1;
} else {
/* first token in the line */
bytecnt = token;
}
}
if (c==' ') sp++;
else {
/* new line */
sp = 0;
fflush(obuf);
}
token = 0;
} else {
/* actual hex and octal conversion */
token =* sp>0 ? 16 : 8;
token =+ c<='9' ? c-'0' : c-'W';
}
lastc = c;
}
if (!(bytecnt & 1)) {
putc(lastb2, obuf);
fflush(obuf);
}
close(ibuf[0]);
close(obuf[0]);
} else if (argc>1) {
diag(argv[1]);
diag(": cannot open\n");
} else {
diag("error: filename missing\n");
}
}
diag(s)
char *s;
{
while(*s)
write(2,s++,1);
}
UPD. 더 빠르고 간단한 버전을 게시했습니다.GitHub, 여기서 구문도 강조 표시됩니다.
답변2
이것은 V6 Unix에서 컴파일할 수 있는 최소한의 C 프로그램입니다.
#define EOF (-1)
int main(){
int i,a,b;
while(scanf("%*7o") != EOF){
for(i = 0; i<8; i++)
if(scanf("%2x%2x",&a,&b) != EOF){putchar(a); putchar(b);}
}
}
결과가 바이트 교환으로 끝나면 2개의 putchar를 반대로 바꿔야 할 수도 있습니다.