\documentclass[ngerman]{article} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \setcounter{secnumdepth}{0} \setcounter{tocdepth}{0} \usepackage{a4} \usepackage{moreverb} \usepackage{url} \usepackage{multicol} \usepackage{babel} \makeatother \begin{document} \title{Umwandlung von HEX in BCD--Zahl in High--Level--Forth\\Oder: Schlag nach bei forthwiki.}[Umwandlung von HEX in BCD] \author{Bernd Paysan\and Michael Kalus} \maketitle \def\figurename{Listing} \begin{abstract} Dieser kleine Beitrag geht auf einen thread in \url{de.comp.lang.forth} zurück. Gleichwohl etliche Mikroprozessoren eine Instruktion haben, die diese Umwandlung unterstützt, wird exemplarisch gezeigt, was zu tun ist, wenn eine solche Unterstützung fehlt oder aus Gründen der Portabilität des Forth solche Instruktion gar nicht genutzt werden soll. \end{abstract} \begin{multicols}{2} Ausgangspunkt war die Frage, ob ein minimaler Forthkern für Steuerungen mit einer spartanischer Ausgabe in Hex auskommt, oder ob die Umwandlung in eine andere Zahlenbasis nötig ist, und ob dann die Division implementiert sein muss. B.\ Paysan zeigte, wie eine dezimale Zahlenausgabe ohne Divison in High--Level--Forth gemacht werden kann. Nehmen wir ein 32--Bit--PC--Forth als Grundlage. (Bei 64 Bit muss man die Maske halt mit 16ern/8ern/4ern/2ern auffüllen). Ihr findet den Code auch im Forth--Wiki. \section{\texttt{2*} und \texttt{bcd2*}} Wenn Du das \verb|bcd2*| in \figurename\ \ref{bcdlisting} durch ein ganz ordinäres \verb|2*| ersetzt, siehst Du, was da eigentlich passiert: Du schiebst die Bits von der einen Zahl in die andere Zahl. Durch das \verb|bcd2*| änderst Du dabei die Codierung der Zahl von binär zu BCD. Wenn man --- wie hier --- den \verb|bcd2*| emulieren muss, ist das kein großer Gewinn gegen die Division, aber wie gesagt: Auf fast allen Controllern ist das nicht nötig, weil die ja so einen BCD--Befehl bereits eingebaut haben. \section{Exkurs: Die BCD--Codierung} Um eine Zahl als BCD--Zahl darzustellen, wird jede dezimale Ziffer (0 bis 9) durch jeweils 4 Bit, also ein Halbbyte (Nibble), im Dualsystem dargestellt ($0000_2$ bis $1001_2$). Die übrigen sechs Werte, die mit 4 Bit darstellbar sind ($1010_2$ bis $1111_2$), stellen keine gültigen BCD--Zahlen dar (Pseudotetraden). Sie werden in manchen Systemen zur Codierung von Vorzeichen, Überträgen oder Kommata verwendet. Zur Codierung von Zahlen mit mehr als einer Dezimalziffer werden die BCD--Darstellungen der einzelnen Ziffern hintereinander gesetzt (zum Beispiel wird die Zahl 2687 als $0010\; 0110\; 1000\; 0111_2$, beziehungsweise ohne trennende Leerzeichen als $0010011010000111_2$ dargestellt). Mit einem Byte (8 Bit) können also zwei Dezimalziffern dargestellt werden. Werden die 4 Bits einer BCD--Zahl jeweils in den niederwertigen Bits codiert und die restlichen 4 Bits mit Nullen aufgefüllt, so spricht man von einer ungepackten BCD--Zahl. Werden beide Hälften eines Bytes mit je einer BCD--Zahl belegt, so nennt man dies entsprechend eine gepackte BCD--Zahl. \end{multicols} \vspace*{-1ex} Quellen:\\ \hspace*{2ex}Bernd Paysan in \url{de.comp.lang.forth}; Mo 13 Mär.\ 2006 14:30\\ \hspace*{2ex}Wikipedia, \emph{BCD-code} \hspace*{\fill}mka\\ \begin{figure*}[b] \begin{quote} \begin{small} \begin{listing}{1} decimal : hex. ( x -- ) 36 emit base @ swap hex u. base ! ; : bcd2* ( bcd1 -- bcd2 ) dup $88888888 and 2/ dup 2/ or swap 2* swap + \ forward carry correction dup $88888888 and over $44444444 and 2 pick $22222222 \ BCD correction and 2* or 2* and 2/ dup 2/ or + ; : hex>bcd ( u -- bcd ) 0 8 cells 0 DO bcd2* over 0< - swap 2* swap LOOP nip ; \ test-code: \ decimal 12345678 hex .s \ Ausgabe: <1> BC614E ok \ hex>bcd hex. \ Ausgabe: $12345678 ok \ \ decimal 98765432 hex .s \ Ausgabe: <1> 5E30A78 ok \ hex>bcd hex. \ Ausgabe: $98765432 ok \end{listing} \end{small} \end{quote} \caption{\label{bcdlisting}Umwandlung nach BCD} \end{figure*} \end{document}