blog · git · desktop · images · contact
2014-07-06
Warum ist an einem gängigen Terminal „^I
“, also „<Ctrl + i>
“,
dasselbe wie ein Druck auf die Tab-Taste? Oder „^M
“ dasselbe wie
Return?
Wenn man ein bisschen damit rumspielt, kommt man schnell auf die Idee:
„Ah, der n
-te Buchstabe im Alphabet produziert ein Byte mit dem Wert
n
“. „I“ ist der neunte Buchstabe und ein Tab hat den Wert „0x09
“.
Passt auch großteils, die Wikipedia-Erklärung schlägt das auch vor.
Ist aber unvollständig und wirkt irgendwie gekünstelt, wenn man es sich
näher anschaut.
Man nehme eine ASCII-Tabelle und teile sie in vier Teile:
+--------------------------------------------------------------------------------------+
| 0 NUL 1 SOH 2 STX 3 ETX 4 EOT 5 ENQ 6 ACK 7 BEL|
| 8 BS 9 HT 10 LF 11 VT 12 FF 13 CR 14 SO 15 SI |
| 16 DLE 17 DC1 18 DC2 19 DC3 20 DC4 21 NAK 22 SYN 23 ETB|
| 24 CAN 25 EM 26 SUB 27 ESC 28 FS 29 GS 30 RS 31 US |
+--------------------------------------------------------------------------------------+
32 SP 33 ! 34 " 35 # 36 $ 37 % 38 & 39 '
40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 /
48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7
56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? <---+
+--------------------------------------------------------------------------------------+ |
| 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G | |
| 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O | |
| 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W | |
| 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ | |
+--------------------------------------------------------------------------------------+ |
96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g |
104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o |
112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w |
120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 DEL <---+
Die Zeichen 0 bis 31 und die 127 sind Steuerzeichen und keine druckbaren Zeichen. Daran sieht man schon, dass „A-Z“ gar nicht ausreicht, um alle Steuerzeichen zu erwischen.
Manche Tasten produzieren direkt ein Steuerzeichen: Die Tabulator-Taste zum Beispiel, Escape oder Enter. Aber nicht alle. Wie kann ich zum Beispiel ein NUL-Byte direkt eingeben? Oder ein BEL für die Terminal-Glocke? Kann ich das überhaupt?
Ja, kann ich. Die Zuordnung funktioniert so: Man nehme den Wert des
Steuerzeichens und invertiere das siebte Bit (gleichbedeutend mit XOR mit
„0x40
“). So wird zum Beispiel aus der 9 des Tabulators eine 73. Das
Zeichen Nummer 73 ist dann ein „I“ und so entsteht „<Ctrl + i>
“.
So geht das mit allen Steuerzeichen, auch mit DEL, was außerhalb des
ersten Blocks liegt. Hier kommt man bei „127 ^ 0x40 = 63
“ heraus, also
bei „^?
“.
Der Rückweg geht natürlich genauso: Lese ich irgendwo „^L
“, dann komme
ich über „76 ^ 0x40 = 12
“ beim Form Feed heraus.
Dieser Weg ist also das, was in der Wikipedia in einem kleinen Satz als „alternative formulation“ kurz erwähnt wird. Ich finde das jedenfalls deutlich konsistenter und einleuchtender als die Erklärung mit dem Alphabet. Naja, ich war nicht bei der Erstellung von ASCII dabei, womöglich ist genau diese Anordnung des Alphabets, die den „Trick“ mit XOR ermöglicht, auch Absicht. :-) Noch schöner wäre es natürlich gewesen, wenn man eines der ersten 32 Steuerzeichen durch DEL ersetzt und somit alle Steuerzeichen im ersten Block gehabt hätte. Dann wäre auch noch Platz für einen Akut gewesen, damit sich der Gravis nicht so alleine fühlen muss.
Die Teilung der Tabelle oben in vier Teile hatte auch einen Grund: So
kann man nämlich alles direkt ablesen, ohne rechnen zu müssen. Man muss
einfach nur zwei Blöcke nach oben oder unten springen. Auch ganz
praktisch ist die Tabelle in „man 7 ascii
“ bei den gängigen
GNU/Linux-Distributionen (für die initiale Erklärung der Thematik ist
sie nur etwas zu unübersichtlich):
Oct Dec Hex Char Oct Dec Hex Char
------------------------------------------------------------------------
000 0 00 NUL '\0' 100 64 40 @
001 1 01 SOH (start of heading) 101 65 41 A
002 2 02 STX (start of text) 102 66 42 B
003 3 03 ETX (end of text) 103 67 43 C
004 4 04 EOT (end of transmission) 104 68 44 D
005 5 05 ENQ (enquiry) 105 69 45 E
006 6 06 ACK (acknowledge) 106 70 46 F
007 7 07 BEL '\a' (bell) 107 71 47 G
... ... ... ... ... ... ... ...
Hier steht sogar alles in derselben Zeile und man sieht sofort, dass man
ein NUL-Byte über „^@
“ eingeben kann.
Auf dieses Thema bin ich heute zufällig gestoßen, als ich auf Sven
Maschecks großartiger Seite stöberte. :-) Dort wird auch noch einmal
darauf hingewiesen, dass man zur Eingabe der meisten Steuerzeichen am
Terminal vorher ein „^V
“ braucht. Das NUL-Byte im folgenden Beispiel
habe ich also über „<Ctrl + v><Ctrl + @>
“ eingegeben:
$ ed
i
^@
.
w foo
2
q
$ od -t x1 foo
0000000 00 0a
0000002
$