diff --git a/20211122/hp-musterloesung-20211122.tex b/20211122/hp-musterloesung-20211122.tex index 7e8d77398c4ef19de65c13e1152f7934a81bce85..79548c0840546ceb221d17afd20bdc20df806635 100644 --- a/20211122/hp-musterloesung-20211122.tex +++ b/20211122/hp-musterloesung-20211122.tex @@ -1,4 +1,4 @@ -% hp-musterloesung-20211115.pdf - Solutions to the Exercises on Low-Level Programming +% hp-musterloesung-20211122.pdf - Solutions to the Exercises on Low-Level Programming % Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski % % This document is free software: you can redistribute it and/or @@ -20,7 +20,7 @@ % Attribution-ShareAlike 3.0 Unported License along with this % document. If not, see <http://creativecommons.org/licenses/>. -% README: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster +% README: Ausgabe von Hexadezimalzahlen, Länge von Strings, LED-Blinkmuster \documentclass[a4paper]{article} diff --git a/20211122/hp-uebung-20211122.tex b/20211122/hp-uebung-20211122.tex index 6e031dd149fdd13f3f11954d86f618491c988053..1f87ecffd4b8cf49807f1c8bfd1cfd9db4739ece 100644 --- a/20211122/hp-uebung-20211122.tex +++ b/20211122/hp-uebung-20211122.tex @@ -20,7 +20,7 @@ % Attribution-ShareAlike 3.0 Unported License along with this % document. If not, see <http://creativecommons.org/licenses/>. -% README: Ausgabe von Hexadezimalzahlen, Einfügen in Strings, LED-Blinkmuster +% README: Ausgabe von Hexadezimalzahlen, Länge von Strings, LED-Blinkmuster \documentclass[a4paper]{article} diff --git a/20211129/aufgabe-1.c b/20211129/aufgabe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..2afae773ac2d564771ab6dfb473eed664070d3e2 --- /dev/null +++ b/20211129/aufgabe-1.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <stdint.h> + +int main (void) +{ + uint64_t x = 4262939000843297096; + char *s = &x; + printf ("%s\n", s); + return 0; +} diff --git a/20211129/aufgabe-3.c b/20211129/aufgabe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..cb09b0e10aade5c202ed88fddcb2e52d700d9915 --- /dev/null +++ b/20211129/aufgabe-3.c @@ -0,0 +1,16 @@ +#include <stdio.h> +#include <stdint.h> + +typedef struct +{ + uint32_t a; + uint64_t b; + uint8_t c; +} three_numbers; + +int main (void) +{ + three_numbers xyz = { 1819042120, 2410670883059281007, 0 }; + printf ("%s\n", &xyz); + return 0; +} diff --git a/20211129/hp-20211129.pdf b/20211129/hp-20211129.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a4d016daec3c32ed1fe1ecc7cd0c0fd09e3815c0 Binary files /dev/null and b/20211129/hp-20211129.pdf differ diff --git a/20211129/hp-20211129.tex b/20211129/hp-20211129.tex new file mode 100644 index 0000000000000000000000000000000000000000..88ee498f82e9a8c4a14d47dab3238dc8d7cbdd7c --- /dev/null +++ b/20211129/hp-20211129.tex @@ -0,0 +1,1057 @@ +% hp-20211129.pdf - Lecture Slides on Low-Level Programming +% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Binärdarstellung negativer Zahlen, Speicherausrichtung – Alignment + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{pdftricks} +\usepackage{tikz} + +\begin{psinputs} + \usepackage[utf8]{inputenc} + \usepackage[german]{babel} + \usepackage[T1]{fontenc} + \usepackage{helvet} + \renewcommand*\familydefault{\sfdefault} + \usepackage{pstricks,pst-grad} +\end{psinputs} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{29.\ November 2021} + +\begin{document} + +\maketitleframe + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \item[4.1] Bit-Operationen + \item[4.2] I/O-Ports + \color{medgreen} + \item[4.3] Interrupts + \item[4.4] volatile-Variable + \color{orange} + \item[4.6] Byte-Reihenfolge -- Endianness + \color{red} + \item[4.7] Binärdarstellung negativer Zahlen + \item[4.8] Speicherausrichtung -- Alignment + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \begin{itemize} + \color{red} + \item[5.1] Differentialgleichungen + \color{black} + \vspace*{-0.1cm} + \item[\dots] + \end{itemize} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + \vspace*{-1cm} + +\end{frame} + +\setcounter{section}{3} +\section{Hardwarenahe Programmierung} +\subsection{Bit-Operationen} +\subsubsection{Zahlensysteme} + +\begin{frame}[fragile] + + \showsection + \vspace*{-\smallskipamount} + \showsubsection + \vspace*{-\medskipamount} + \showsubsubsection + + \begin{tabular}{rlrl} + Basis & Name & Beispiel & Anwendung \\[\smallskipamount] + 2 & Binärsystem & 1\,0000\,0011 & Bit-Operationen \\ + 8 & Oktalsystem & \lstinline,0403, & Dateizugriffsrechte (Unix) \\ + 10 & Dezimalsystem & \lstinline,259, & Alltag \\ + 16 & Hexadezimalsystem & \lstinline,0x103, & Bit-Operationen \\ + 256 & (keiner gebräuchlich) & 0.0.1.3 & IP-Adressen (IPv4) + \end{tabular} + + \bigskip + + \begin{itemize} + \item + Computer rechnen im Binärsystem. + \item + Für viele Anwendungen (z.\,B.\ I/O-Ports, Grafik, \dots) ist es notwendig,\\ + Bits in Zahlen einzeln ansprechen zu können. + \end{itemize} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsubsection + + \begin{tabular}{rlrlrc} + \qquad 000 & \bf 0 \hspace*{1.5cm} & 0000 & \bf 0 & \quad 1000 & \bf 8\\ + 001 & \bf 1 & 0001 & \bf 1 & 1001 & \bf 9\\ + 010 & \bf 2 & 0010 & \bf 2 & 1010 & \bf A\\ + 011 & \bf 3 & 0011 & \bf 3 & 1011 & \bf B\\[\smallskipamount] + 100 & \bf 4 & 0100 & \bf 4 & 1100 & \bf C\\ + 101 & \bf 5 & 0101 & \bf 5 & 1101 & \bf D\\ + 110 & \bf 6 & 0110 & \bf 6 & 1110 & \bf E\\ + 111 & \bf 7 & 0111 & \bf 7 & 1111 & \bf F\\ + \end{tabular} + + \medskip + + \begin{itemize} + \item + Oktal- und Hexadezimalzahlen lassen sich ziffernweise\\ + in Binär-Zahlen umrechnen. + \item + Hexadezimalzahlen sind eine Kurzschreibweise für Binärzahlen,\\ + gruppiert zu jeweils 4 Bits. + \item + Oktalzahlen sind eine Kurzschreibweise für Binärzahlen,\\ + gruppiert zu jeweils 3 Bits. + \item + Trotz Taschenrechner u.\,ä.\ lohnt es sich,\\ + die o.\,a.\ Umrechnungstabelle \textbf{auswendig} zu kennen. + \end{itemize} + +\end{frame} + +\subsubsection{Bit-Operationen in C} + +\begin{frame}[fragile] + + \showsubsubsection + + \begin{tabular}{lll} + C-Operator & Verknüpfung & Anwendung \\[\smallskipamount] + \lstinline,&, & Und & Bits gezielt löschen \\ + \lstinline,|, & Oder & Bits gezielt setzen \\ + \lstinline,^, & Exklusiv-Oder & Bits gezielt invertieren \\ + \lstinline,~, & Nicht & Alle Bits invertieren \\[\smallskipamount] + \lstinline,<<, & Verschiebung nach links & Maske generieren \\ + \lstinline,>>, & Verschiebung nach rechts & Bits isolieren + \end{tabular} + + \bigskip + + Numerierung der Bits: von rechts ab 0 + + \medskip + + \begin{tabular}{ll} + Bit Nr.\ 3 auf 1 setzen: & + \lstinline,a |= 1 << 3;, \\ + Bit Nr.\ 4 auf 0 setzen: & + \lstinline,a &= ~(1 << 4);, \\ + Bit Nr.\ 0 invertieren: & + \lstinline,a ^= 1 << 0;, + \end{tabular} + + \smallskip + + ~~Abfrage, ob Bit Nr.\ 1 gesetzt ist:\quad + \lstinline{if (a & (1 << 1))} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsubsection + + C-Datentypen für Bit-Operationen: + \smallskip\par + \lstinline{#include <stdint.h>} + \medskip\par + \begin{tabular}{lllll} + & 8 Bit & 16 Bit & 32 Bit & 64 Bit \\ + mit Vorzeichen & \lstinline,int8_t, + & \lstinline,int16_t, + & \lstinline,int32_t, + & \lstinline,int64_t, \\ + ohne Vorzeichen & \lstinline,uint8_t, + & \lstinline,uint16_t, + & \lstinline,uint32_t, + & \lstinline,uint64_t, + \end{tabular} + + \bigskip + \bigskip + + Ausgabe: + \smallskip\par + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + #include <inttypes.h> + ... + uint64_t x = 42; + printf ("Die Antwort lautet: %" PRIu64 "\n", x); + \end{lstlisting} + +\end{frame} + +\subsection{I/O-Ports} + +\begin{frame}[fragile] + +% \showsection + \showsubsection + \vspace*{-1.5\medskipamount} + {\large\textbf{\color{structure}5.3\quad Interrupts}} + + \bigskip + + Kommunikation mit externen Geräten + + \bigskip + + \begin{center} + \includegraphics{io-ports-and-interrupts.pdf} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + In Output-Port schreiben = Aktoren ansteuern + + Beispiel: LED + + \medskip + + \begin{lstlisting} + #include <avr/io.h> + ... + DDRC = 0x70; + PORTC = 0x40; + \end{lstlisting} + \begin{picture}(0,0) + \put(3,0.67){\begin{minipage}{3cm} + \color{red}% + binär: 0111\,0000\\ + binär: 0100\,0000 + \end{minipage}} + \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}} + \end{picture} + + \bigskip + + \lstinline{DDR} = Data Direction Register\\ + Bit = 1 für Output-Port\\ + Bit = 0 für Input-Port + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Aus Input-Port lesen = Sensoren abfragen + + Beispiel: Taster + + \medskip + + \begin{lstlisting} + #include <avr/io.h> + ... + DDRC = 0xfd; + while ((PINC & 0x02) == 0) + ; /* just wait */ + \end{lstlisting} + \begin{picture}(0,0)(-1.5,-0.42) + \put(3,0.67){\begin{minipage}{3cm} + \color{red}% + binär: 1111\,1101\\ + binär: 0000\,0010 + \end{minipage}} + \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}} + \end{picture} + + \bigskip + + \lstinline{DDR} = Data Direction Register\\ + Bit = 1 für Output-Port\\ + Bit = 0 für Input-Port + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \bigskip + + Praktikumsaufgabe: Druckknopfampel + +\end{frame} + +\subsection{Interrupts} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: eingebaute Uhr\hfill + \makebox(0,0)[tr]{% + \only<1->{\begin{minipage}[t]{4.7cm} + \vspace*{-0.3cm}% + statt Zählschleife (\lstinline{_delay_ms}):\\ + Hauptprogramm kann\\ + andere Dinge tun + \end{minipage}}% + } + + \medskip + + \begin{lstlisting} + #include <avr/interrupt.h> + + ... + + + ISR (TIMER0B_COMP_vect) + { + PORTD ^= 0x40; + } + \end{lstlisting} + \begin{picture}(0,0) + \color{red} + \put(1.9,3.1){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-1.4,-1.0);}}} + \put(2.0,3.2){\makebox(0,0)[l]{"`Dies ist ein Interrupt-Handler."'}} + \put(2.3,2.6){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.55);}}} + \put(2.4,2.6){\makebox(0,0)[l]{Interrupt-Vektor darauf zeigen lassen}} + \end{picture} + + Initialisierung über spezielle Ports: + \lstinline{TCCR0B}, \lstinline{TIMSK0} + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \vspace*{-2.5cm}\hfill + {\color{red}Herstellerspezifisch!}% + \hspace*{1cm} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: Taster\hfill + \makebox(0,0)[tr]{% + \begin{minipage}[t]{4.7cm} + \vspace*{-0.3cm}% + statt \newterm{Busy Waiting\/}:\\ + Hauptprogramm kann\\ + andere Dinge tun + \end{minipage}} + + \medskip + + \begin{lstlisting} + #include <avr/interrupt.h> + ... + + ISR (INT0_vect) + { + PORTD ^= 0x40; + } + \end{lstlisting} + + \medskip + + Initialisierung über spezielle Ports: + \lstinline{EICRA}, \lstinline{EIMSK} + + \bigskip + + \emph{Details: siehe Datenblatt und Schaltplan} + + \vspace*{-2.5cm}\hfill + {\color{red}Herstellerspezifisch!}% + \hspace*{1cm} + +\end{frame} + +\subsection{volatile-Variable} + +\begin{frame}[fragile] + + \showsubsection + + Externes Gerät ruft (per Stromsignal) Unterprogramm auf + + Zeiger hinterlegen: "`Interrupt-Vektor"' + + Beispiel: Taster + + \vspace*{-2.5pt} + + \begin{minipage}[t]{5cm} + \begin{onlyenv}<1> + \begin{lstlisting}[gobble=8] + ¡#include <avr/interrupt.h> + ... + + uint8_t key_pressed = 0; + + ISR (INT0_vect) + { + key_pressed = 1; + }¿ + \end{lstlisting} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{lstlisting}[gobble=8] + ¡#include <avr/interrupt.h> + ... + + volatile uint8_t key_pressed = 0; + + ISR (INT0_vect) + { + key_pressed = 1; + }¿ + \end{lstlisting} + \end{onlyenv} + \end{minipage}\hfill + \begin{minipage}[t]{6cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + ... + + while (1) + { + while (!key_pressed) + ; /* just wait */ + PORTD ^= 0x40; + key_pressed = 0; + } + return 0; + }¿ + \end{lstlisting} + \end{minipage} + + \pause + \begin{picture}(0,0) + \color{red} + \put(10.3,4.0){\makebox(0,0)[b]{\begin{minipage}{6cm} + \begin{center} + \textbf{volatile}:\\ + Speicherzugriff\\ + nicht wegoptimieren + \end{center} + \end{minipage}}} + \put(10.3,3.95){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.5,-0.9);}}} + \end{picture} + +\end{frame} + +\iffalse + +\begin{frame}[fragile] + + \showsubsection + + Was ist eigentlich \lstinline{PORTD}? + + \bigskip + \pause + + \lstinline[style=cmd]{avr-gcc -Wall -Os -mmcu=atmega328p blink-3.c -E} + + \bigskip + \pause + \lstinline{PORTD = 0x01;}\\ + \textarrow\quad + \lstinline[style=terminal]{(*(volatile uint8_t *)((0x0B) + 0x20)) = 0x01;}\\ + \pause + \begin{picture}(0,2)(0,-1.7) + \color{red} + \put(5.75,0.3){$\underbrace{\rule{2.95cm}{0pt}}_{\mbox{Zahl: \lstinline|0x2B|}}$} + \pause + \put(1.55,0.3){$\underbrace{\rule{4.0cm}{0pt}}_{\mbox{\shortstack[t]{Umwandlung in Zeiger\\ + auf \lstinline|volatile uint8_t|}}}$} + \pause + \put(1.32,-1){\makebox(0,0)[b]{\tikz{\draw[-latex](0,0)--(0,1.3)}}} + \put(1.12,-1.1){\makebox(0,0)[tl]{Dereferenzierung des Zeigers}} + \end{picture} + + \pause + \textarrow\quad + \lstinline|volatile uint8_t|-Variable an Speicheradresse \lstinline|0x2B| + + \pause + \bigskip + \bigskip + + \textarrow\quad + \lstinline|PORTA = PORTB = PORTC = PORTD = 0| ist eine schlechte Idee. + +\end{frame} + +\fi + +\subsection{Byte-Reihenfolge -- Endianness} +\subsubsection{Konzept} + +\begin{frame}[fragile] + + \showsubsection + \showsubsubsection + + Eine Zahl geht über mehrere Speicherzellen.\\ + Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen + + \smallskip + + Welche Bits liegen wo? + + \pause + \bigskip + + $1027 = 1024 + 2 + 1 = 0000\,0100\,0000\,0011_2 = 0403_{16}$ + + \pause + \bigskip + Speicherzellen: + + \medskip + \begin{tabular}{|c|c|l}\cline{1-2} + \raisebox{-0.25ex}{04} & \raisebox{-0.25ex}{03} & \strut Big-Endian "`großes Ende zuerst"' \\\cline{1-2} + \multicolumn{2}{c}{} & \pause für Menschen leichter lesbar \pause \\ + \multicolumn{3}{c}{} \\[-5pt]\cline{1-2} + \raisebox{-0.25ex}{03} & \raisebox{-0.25ex}{04} & \strut Little-Endian "`kleines Ende zuerst"' \\\cline{1-2} + \multicolumn{2}{c}{} & \pause bei Additionen effizienter + \end{tabular} + + \pause + \medskip + \textarrow\ Geschmackssache + \pause\\ + \quad\textbf{\dots\ außer bei Datenaustausch!} + +% \pause +% \bigskip +% +% Aber: nicht verwechseln! \qquad $0304_{16} = 772$ + +\end{frame} + +\begin{frame} + + \showsubsection + \showsubsubsection + + Eine Zahl geht über mehrere Speicherzellen.\\ + Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen + + \smallskip + + Welche Bits liegen wo? + + \medskip + + \textarrow\ Geschmackssache\\ + \textbf{\dots\ außer bei Datenaustausch!} + + \begin{itemize} + \item + Dateiformate + \item + Datenübertragung + \end{itemize} + +\end{frame} + +\subsubsection{Dateiformate} + +\begin{frame} + + \showsubsection + \showsubsubsection + + Audio-Formate: Reihenfolge der Bytes in 16- und 32-Bit-Zahlen + \begin{itemize} + \item + RIFF-WAVE-Dateien (\file{.wav}): Little-Endian + \item + Au-Dateien (\file{.au}): Big-Endian + \pause + \item + ältere AIFF-Dateien (\file{.aiff}): Big-Endian + \item + neuere AIFF-Dateien (\file{.aiff}): Little-Endian + \end{itemize} + + \pause + \bigskip + + Grafik-Formate: Reihenfolge der Bits in den Bytes + \begin{itemize} + \item + PBM-Dateien: Big-Endian\only<4->{, MSB first} + \item + XBM-Dateien: Little-Endian\only<4->{, LSB first} + \end{itemize} + \only<4->{MSB/LSB = most/least significant bit} + +\end{frame} + +\subsubsection{Datenübertragung} + +\begin{frame} + + \showsubsection + \showsubsubsection + + \begin{itemize} + \item + RS-232 (serielle Schnittstelle): LSB first + \item + I$^2$C: MSB first + \item + USB: beides + \pause + \medskip + \item + Ethernet: LSB first + \item + TCP/IP (Internet): Big-Endian + \end{itemize} + +\end{frame} + +\subsection{Binärdarstellung negativer Zahlen} + +\begin{frame}[fragile] + + \showsubsection + + Speicher ist begrenzt!\\ + \textarrow\ feste Anzahl von Bits + + \medskip + + 8-Bit-Zahlen ohne Vorzeichen: \lstinline{uint8_t}\\ + \textarrow\ Zahlenwerte von \lstinline{0x00} bis \lstinline{0xff} = 0 bis 255\\ + \pause + \textarrow\ 255 + 1 = 0 + + \pause + \medskip + + 8-Bit-Zahlen mit Vorzeichen: \lstinline{int8_t}\\ + \lstinline{0xff} = 255 ist die "`natürliche"' Schreibweise für $-1$.\\ + \pause + \textarrow\ Zweierkomplement + + \pause + \medskip + + Oberstes Bit = 1: negativ\\ + Oberstes Bit = 0: positiv\\ + \textarrow\ 127 + 1 = $-128$ + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Speicher ist begrenzt!\\ + \textarrow\ feste Anzahl von Bits + + \medskip + + 16-Bit-Zahlen ohne Vorzeichen: + \lstinline{uint16_t}\hfill\lstinline{uint8_t}\\ + \textarrow\ Zahlenwerte von \lstinline{0x0000} bis \lstinline{0xffff} + = 0 bis 65535\hfill 0 bis 255\\ + \textarrow\ 65535 + 1 = 0\hfill 255 + 1 = 0 + + \medskip + + 16-Bit-Zahlen mit Vorzeichen: + \lstinline{int16_t}\hfill\lstinline{int8_t}\\ + \lstinline{0xffff} = 66535 ist die "`natürliche"' Schreibweise für $-1$.\hfill + \lstinline{0xff} = 255 = $-1$\\ + \textarrow\ Zweierkomplement + + \medskip + + Oberstes Bit = 1: negativ\\ + Oberstes Bit = 0: positiv\\ + \textarrow\ 32767 + 1 = $-32768$ + + \bigskip + Literatur: \url{http://xkcd.com/571/} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Frage: \emph{Für welche Zahl steht der Speicherinhalt\, + \raisebox{2pt}{% + \tabcolsep0.25em + \begin{tabular}{|c|c|}\hline + \rule{0pt}{11pt}a3 & 90 \\\hline + \end{tabular}} + (hexadezimal)?} + + \pause + \smallskip + Antwort: \emph{Das kommt darauf an.} ;--) + + \pause + \medskip + Little-Endian: + + \smallskip + + \begin{tabular}{lrl} + als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\ + als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\ + als \lstinline,int16_t,: & $-28509$\\ + als \lstinline,uint16_t,: & $37027$\\ + \lstinline,int32_t, oder größer: & $37027$ + & (zusätzliche Bytes mit Nullen aufgefüllt) + \end{tabular} + + \pause + \medskip + Big-Endian: + + \smallskip + + \begin{tabular}{lrl} + als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\ + als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\ + als \lstinline,int16_t,: & $-23664$\\ + als \lstinline,uint16_t,: & $41872$\\ als \lstinline,int32_t,: & $-1550843904$ & (zusätzliche Bytes\\ + als \lstinline,uint32_t,: & $2744123392$ & mit Nullen aufgefüllt)\\ + als \lstinline,int64_t,: & $-6660823848880963584$\\ + als \lstinline,uint64_t,: & $11785920224828588032$\\ + \end{tabular} + + \vspace*{-1cm} + +\end{frame} + +\subsection{Speicherausrichtung -- Alignment} + +\begin{frame}[fragile] + + \showsubsection + + \begin{lstlisting} + #include <stdint.h> + + uint8_t a; + uint16_t b; + uint8_t c; + \end{lstlisting} + + \pause + \bigskip + + Speicheradresse durch 2 teilbar -- "`16-Bit-Alignment"' + \begin{itemize} + \item + 2-Byte-Operation: effizienter + \pause + \item + \dots\ oder sogar nur dann erlaubt + \pause + \arrowitem + Compiler optimiert Speicherausrichtung + \end{itemize} + + \medskip + + \pause + \begin{minipage}{3cm} + \begin{lstlisting}[gobble=6] + ¡uint8_t a; + uint8_t dummy; + uint16_t b; + uint8_t c;¿ + \end{lstlisting} + \end{minipage} + \pause + \begin{minipage}{3cm} + \begin{lstlisting}[gobble=6] + ¡uint8_t a; + uint8_t c; + uint16_t b;¿ + \end{lstlisting} + \end{minipage} + + \pause + \vspace{-1.75cm} + \strut\hfill + \begin{minipage}{6.5cm} + Fazit: + \begin{itemize} + \item + \textbf{Adressen von Variablen\\ + sind systemabhängig} + \item + Bei Definition von Datenformaten\\ + Alignment beachten \textarrow\ effizienter + \end{itemize} + \end{minipage} + +\end{frame} + +\section{Algorithmen} +\subsection{Differentialgleichungen} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung} + + \strut\hfill + \begin{minipage}{2.5cm} + \vspace*{0.6cm} + \begin{align*} + x'(t) &= v_x(t) \\[0.65cm] + y'(t) &= v_y(t) \\[0.75cm] + v_x'(t) &= 0 \\[0.65cm] + v_y'(t) &= -g + \end{align*} + \vspace*{0.0cm} + \end{minipage}% + \only<1>{\hspace*{9.49cm}}\strut + \only<2->{\hfill$\Rightarrow$\hfill}% + \begin{onlyenv}<2-8> + \begin{minipage}{8.3cm} + \begin{align*} + x(t) &= \int v_x(t)\,dt + \visible<4->{= \int v_{0x}\,dt} + \visible<5->{= x_0 + v_{0x}\cdot t}\\[\medskipamount] + y(t) &= \int v_y(t)\,dt + \visible<7->{= \int v_{0y} - g\cdot t\,dt} + \visible<8->{= y_0 + v_{0y}\cdot t + - {\textstyle\frac12}gt^2}\\[\bigskipamount] + v_x(t) &= \int 0\,dt + \visible<3->{= v_{0x}} \\[\medskipamount] + v_y(t) &= \int -g\,dt + \visible<6->{= v_{0y} - g\cdot t} + \end{align*} + \end{minipage}% + \end{onlyenv}% + \begin{onlyenv}<9-> + \begin{minipage}{3.5cm} + \vspace*{0.5cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡x += vx * dt;¿ + \end{lstlisting} + \vspace{0.75cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡y += vy * dt;¿ + \end{lstlisting} + \vspace{0.90cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡vx += 0 * dt;¿ + \end{lstlisting} + \vspace{0.75cm} + \begin{lstlisting}[gobble=8,xleftmargin=0.5em] + ¡vy += -g * dt;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}{5.13cm} + Siehe: \file{gtk-13.c} + \end{minipage} + \end{onlyenv}% + \hfill\strut + +\end{frame} + +\begin{frame}[fragile] + \showsection + \showsubsection + + \textbf{Beispiel 1: Gleichmäßig beschleunigte Bewegung} + + \medskip + + \textbf{Beispiel 2: Mathematisches Pendel} + + \vspace*{-2\bigskipamount} + + \begin{picture}(0,0) + \put(8,-6.5){\includegraphics{pendulum.pdf}} + \end{picture} + + \begin{eqnarray*} + \varphi'(t) &=& \omega(t) \\[\smallskipamount] + \omega'(t) &=& -\frac{g}{l}\cdot\sin\varphi(t)\hspace*{7.1cm} + \end{eqnarray*} + \vspace*{-1.5\medskipamount} + \begin{itemize} + \item + Von Hand (analytisch):\\ + Lösung raten (Ansatz), Parameter berechnen + \item + Mit Computer (numerisch):\\ + Eulersches Polygonzugverfahren + \end{itemize} + \smallskip + \begin{lstlisting}[gobble=0] + phi += dt * omega; + omega += - dt * g / l * sin (phi); + \end{lstlisting} + + \pause + \bigskip + + \textbf{Beispiel 3: Weltraum-Simulation} + + Praktikumsaufgabe + \vspace*{-1cm} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \begin{itemize} + \item[3.1] Der Präprozessor + \item[3.2] Bibliotheken einbinden + \item[3.3] Bibliotheken verwenden + \color{medgreen} + \item[3.4] Projekt organisieren: make + \end{itemize} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \color{red} + \item[4.1] Bit-Operationen + \item[4.2] I/O-Ports + \item[4.3] Interrupts + \vspace*{-0.1cm} + \item[\dots] + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \begin{itemize} + \color{medgreen} + \item[5.1] Differentialgleichungen + \color{black} + \vspace*{-0.1cm} + \item[\dots] + \end{itemize} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + \vspace*{-1cm} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} + \begin{itemize} + \item[4.1] Bit-Operationen + \item[4.2] I/O-Ports + \item[4.3] Interrupts + \item[4.4] volatile-Variable + \color{medgreen} + \item[4.6] Byte-Reihenfolge -- Endianness + \item[4.7] Binärdarstellung negativer Zahlen + \item[4.8] Speicherausrichtung -- Alignment + \end{itemize} + \item[\textbf{5}] \textbf{Algorithmen} + \begin{itemize} + \color{medgreen} + \item[5.1] Differentialgleichungen + \color{black} + \vspace*{-0.1cm} + \item[\dots] + \end{itemize} + \item[\textbf{\dots}] +% \item[\textbf{4}] \textbf{Hardwarenahe Programmierung} +% \item[\textbf{5}] \textbf{Algorithmen} +% \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke} + \end{itemize} + +\end{frame} + +\end{document} diff --git a/20211129/hp-2021ws-p3.pdf b/20211129/hp-2021ws-p3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cc20aac76609abda47a89ad4c722bd7c29405af0 Binary files /dev/null and b/20211129/hp-2021ws-p3.pdf differ diff --git a/20211129/hp-2021ws-p3.tex b/20211129/hp-2021ws-p3.tex new file mode 100644 index 0000000000000000000000000000000000000000..45a58ee1a664c36b85596b6d9f08dff349cfd2d3 --- /dev/null +++ b/20211129/hp-2021ws-p3.tex @@ -0,0 +1,201 @@ +% hp-2021ws-p3.pdf - Labor Notes on Low-Level Programming +% Copyright (C) 2014, 2015, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Versuch 3: Weltraum-Simulation + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{multicol} +%\usepackage{sfmath} + +\sloppy +\raggedcolumns +\pagestyle{empty} +\addtolength{\textheight}{1cm} +\newcommand{\sep}{~$\cdot$~} +\newcommand{\mylicense}{CC BY-SA (Version 4.0) oder GNU GPL (Version 3 oder höher)} + +\begin{document} + + \makebox(0,0.005)[tl]{\includegraphics[scale=0.72]{logo-hochschule-bochum-cvh-text-v2.pdf}}\hfill + \makebox(0,0)[tr]{\includegraphics[scale=0.5]{logo-hochschule-bochum.pdf}} + \par\bigskip\bigskip + \begin{center} + \Large\textbf{Praktikumsversuch 3: Weltraum-Simulation} + \par\medskip + \normalsize Hardwarenahe Programmierung\sep + Wintersemester 2021/22\sep + Prof.~Dr.~Peter Gerwinski + \end{center} + + Aufgabe: Schreiben Sie ein C-Programm, + das die Bahnen von beliebig vielen Massenpunkten unter Einfluß der Gravitation + simuliert und in bewegter Grafik darstellt. + + \begin{multicols}{2} + + \begin{itemize} + \item + Zwei Massenpunkte ("`Himmelskörper"') mit den Massen $m_i$ und $m_j$ + an den Orten $\vec{r}_i$ und $\vec{r}_j$ ziehen einander an. + Diese Kraft heißt Gravitation. Sie hat den Betrag: + \begin{equation} + |\vec{F}_{ij}| = \frac{m_j\cdot m_i\cdot G}{|\vec{r}_j - \vec{r}_i|^2} + \end{equation} + Hierbei ist $G$ eine Konstante (Gravitationskonstante). + + \item + Die auf einen Himmelskörper wirkende Gesamtkraft $\vec{F}_i$ + ergibt sich als Summe der von allen anderen Himmelskörpern herrührenden + Gravitationskräfte: + \begin{equation} + \vec{F}_i = \sum_{j=0,\,j\ne i}^{N - 1} \vec{F}_{ij} + \end{equation} + + \item + Die Gravitationskraft beschleunigt jeden Himmelskörper gemäß: + \begin{equation} + \vec{F_i} = m_i\cdot \vec{a_i} + \end{equation} + + \item + Beispiel: Wir betrachten zwei Himmelskörper. Einer davon ("`Zentralgestirn"') + ruht im Zentrum ($\vec{r}_0 = 0$, $\vec{v}_0 = 0$) + und hat eine wesentlich größere Masse als der andere + ("`Satellit"', $m_1 \ll m_0$). Mit geeignetem Anfangsort $\vec{r}_1$ + und geeigneter Anfangsgeschwindigkeit $\vec{v}_1$ beschreibt dann + der Satellit eine elliptische Umlaufbahn um das Zentralgestirn. + + \item + Wir rechnen in zwei Dimensionen $x$ und $y$. + + \item + Für die Zerlegung einer Kraft $\vec{F}_{ij}$ in $x$- und $y$-Komponenten + benötigen Sie nur die Grundrechenarten und die Wurzelfunktion, + jedoch insbesondere \emph{keine} trigonometrischen Funktionen: + \begin{equation} + \vec{F}_{ij} = |\vec{F}_{ij}| \cdot \frac{\vec{r}_j - \vec{r}_i}{|\vec{r}_j - \vec{r}_i|} + \end{equation} + + \item + Die Wurzelfunktion \lstinline{sqrt()} finden Sie + in der Mathematik-Bibliothek. + Um diese zu nutzen, verwenden Sie \lstinline{#include <math.h>} im Quelltext, + und geben Sie beim \lstinline[style=cmd]{gcc}-Aufruf + \lstinline[style=cmd]{-lm} mit an. + + \columnbreak + + \item + Für die Simulation betrachten wir das System in kurzen Zeitintervallen $dt$ + und berechnen die Änderungen des Ortes $\vec{r}_i = (x_i,y_i)$ + und der Geschwindigkeit $\vec{v}_i = (v_{xi},v_{yi})$ jedes Himmelskörpers + mit Hilfe des expliziten Eulerschen Polygonzugverfahrens. + \par + (Wer möchte, darf natürlich auch andere Verfahren anwenden, + beispielsweise das klassische Runge-Kutta-Verfahren 4.~Ordnung.) + + \item + Für eine derartige Simulation + einschließlich ihrer Darstellung als bewegte Grafik + können Sie sich von dem Beispiel-Programm \gitfile{hp}{2020ws/20201217}{gtk-16.c} + inspirieren lassen. +% (Compilieren mit: +% \lstinline[style=cmd]{gcc} +% \lstinline[style=cmd]{-Wall} +% \lstinline[style=cmd]{-O} +% \lstinline[style=cmd]{gtk-16.c} +% \lstinline[style=cmd]{$(pkg-config} +% \lstinline[style=cmd]{--cflags} +% \lstinline[style=cmd]{--libs} +% \lstinline[style=cmd]{gtk+-3.0)} +% \lstinline[style=cmd]{-o} +% \lstinline[style=cmd]{gtk-16}) + + \item + In einer \file{GTK+}-\lstinline{drawing_area} + liegt der Nullpunkt der Zeichnung oben links, + eine Längeneinheit entspricht einem Pixel, + und die $y$-Koordinate wächst nach unten. + Es empfiehlt sich, die Koordinaten so umzurechnen, + daß der Nullpunkt in der Mitte der Zeichnung liegt, + die Längeneinheit Ihrem persönlichen Geschmack entspricht + und die $y$-Koordinate nach oben wächst. + + \item + Beispiel-Szenarien für 3 oder mehr Körper: + \vspace{-\smallskipamount} + \begin{itemize}\itemsep0pt + \item + Planet mit Mond umkreist Sonne + \item + Sonne mit mehreren Planeten, die sich gegenseitig beeinflussen + \item + zwei Sonnen umkreisen sich gegenseitig, Planet kreist drumherum + \item + Raumsonde besucht nacheinander mehrere Planeten + \end{itemize} + + \item + \textbf{Hinweis:} + Speichern Sie die verschiedenen Körper nicht als separate Variable, + sondern in einem Array. Ihr Programm wird dadurch nicht nur flexibler, + sondern auch übersichtlicher und weniger fehleranfällig. + + \item + \textbf{Online-Abgabe:} + Ihre Quelltexte mit den Lösungen der Praktikumsaufgabe schicken Sie bitte + per E-Mail an \file{peter.gerwinski@hs-bochum.de} + mit dem \textbf{Betreff:} \lstinline[style=terminal]{Poo6va2U} + unter Angabe von Name, Matrikel-Nummer, + Studiengang (MI/MP/TI) und Studienmodell (KIA/KIS/GS). + + \end{itemize} + + \end{multicols} + + \vspace*{-\bigskipamount} + + \strut\hfill\emph{Viel Erfolg!}\qquad\qquad + + \vfill + + \begingroup + + \small + + \setlength{\leftskip}{3cm} + + Stand: 29.\ November 2021 + +% Soweit nicht anders angegeben:\\ + Copyright \copyright\ 2014, 2015, 2018, 2019, 2020, 2021\quad Peter Gerwinski\\ + Lizenz: \mylicense + + Sie können diese Praktikumsunterlagen einschließlich \LaTeX-Quelltext + und Beispielprogramm herunterladen unter: + \url{https://gitlab.cvh-server.de/pgerwinski/hp} + + \endgroup + +\end{document} diff --git a/20211129/hp-musterloesung-20211129.pdf b/20211129/hp-musterloesung-20211129.pdf new file mode 100644 index 0000000000000000000000000000000000000000..82f8ec915be7e743cd26fbfb963d4fb12f86796f Binary files /dev/null and b/20211129/hp-musterloesung-20211129.pdf differ diff --git a/20211129/hp-musterloesung-20211129.tex b/20211129/hp-musterloesung-20211129.tex new file mode 100644 index 0000000000000000000000000000000000000000..a9e66d107cbaac3fe1f7ed336581eb7623ea650f --- /dev/null +++ b/20211129/hp-musterloesung-20211129.tex @@ -0,0 +1,484 @@ +% hp-musterloesung-20211129.pdf - Solutions to the Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Trickprogrammierung, Thermometer-Baustein an I²C-Bus + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{gensymb} + +\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C} +\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 29.\ November 2021} + + \exercise{Trickprogrammierung} + + Wir betrachten das folgende Programm (Datei: \gitfile{hp}{2021ws/20211129}{aufgabe-1.c}): + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + + int main (void) + { + uint64_t x = 4262939000843297096; + char *s = &x; + printf ("%s\n", s); + return 0; + } + \end{lstlisting} + Das Programm wird compiliert und auf einem 64-Bit-Little-Endian-Computer ausgeführt: + \begin{lstlisting}[style=terminal] + $ ¡gcc -Wall -O aufgabe-1.c -o aufgabe-1¿ + aufgabe-1.c: In function `main': + aufgabe-1.c:7:13: warning: initialization from incompatible pointer type [...] + $ ¡./aufgabe-1¿ + Hallo + \end{lstlisting} + + \begin{itemize} + \item[(a)] + Erklären Sie die Warnung beim Compilieren. \points{2} + \item[(b)] + Erklären Sie die Ausgabe des Programms. \points{5} + \item[(c)] + Wie würde die Ausgabe des Programms auf einem 64-Bit-Big-Endian-Computer lauten? \points{3} + \end{itemize} + Hinweis: Modifizieren Sie das Programm + und lassen Sie sich Speicherinhalte ausgeben. + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Erklären Sie die Warnung beim Compilieren.} + + Zeile 7 des Programms enthält eine Zuweisung von \lstinline{&x} + an die Variable \lstinline{s}. + Der Ausdruck \lstinline{&x} steht für die Speicheradresse der Variablen \lstinline{x}, + ist also ein Zeiger auf \lstinline{x}, + also ein Zeiger auf eine \lstinline{uint64_t}. + Die Variable \lstinline{s} hingegen ist ein Zeiger auf \lstinline{char}, + also ein Zeiger auf eine viel kleinere Zahl, + also ein anderer Zeigertyp. + + \item[(b)] + \textbf{Erklären Sie die Ausgabe des Programms.} + + Die 64-Bit-Zahl (\lstinline{uint64_t}) \lstinline{x} + belegt 8 Speicherzellen (Bytes) von jeweils 8 Bit. + Um herauszufinden, was diese enthalten, + lassen wir uns \lstinline{x} als Hexadezimalzahl ausgeben, + z.\,B.\ mittels \lstinline{printf ("%lx\n", x)} + (auf 32-Bit-Rechnern: \lstinline{"%llx\n"}) + oder mittels \lstinline{printf ("%" PRIx64 "\n", x)} + (erfordert \lstinline{#include <inttypes.h>} + -- siehe die Datei \gitfile{hp}{2021ws/20211129}{loesung-1-1.c}). + Das Ergebnis lautet: + \begin{lstlisting}[style=terminal,gobble=8] + 3b29006f6c6c6148 + \end{lstlisting} + Auf einzelne Bytes verteilt: + \begin{lstlisting}[style=terminal,gobble=8] + 3b 29 00 6f 6c 6c 61 48 + \end{lstlisting} + Auf einem Little-Endian-Rechner + ist die Reihenfolge der Bytes in den Speicherzellen genau umgekehrt: + \begin{lstlisting}[style=terminal,gobble=8] + 48 61 6c 6c 6f 00 29 3b + \end{lstlisting} + Wenn wir uns diese Bytes als Zeichen ausgeben lassen + (\lstinline{printf()} mit \lstinline{%c} -- siehe die Datei \gitfile{hp}{2021ws/20211129}{loesung-1-2.c}), + erhalten wir: + \begin{lstlisting}[style=terminal,gobble=8] + H a l l o ) ; + \end{lstlisting} + Das Zeichen hinter "`Hallo"' ist ein Null-Symbol (Zahlenwert 0) + und wird von \lstinline{printf ("%s")} als Ende des Strings erkannt. + Damit ist die Ausgabe \lstinline[style=terminal]{Hallo} + des Programms erklärt. + + \goodbreak + \item[(c)] + \textbf{Wie würde die Ausgabe des Programms auf einem 64-Bit-Big-Endian-Computer lauten?} + + Auf einem Big-Endian-Computer (egal, wieviele Bits die Prozessorregister haben) + ist die Reihenfolge der Bytes in den Speicherzellen genau umgekehrt + wie auf einem Little-Endian-Computer, hier also: + \begin{lstlisting}[style=terminal,gobble=8] + 3b 29 00 6f 6c 6c 61 48 + \end{lstlisting} + \lstinline{printf ("%s")} gibt in diesem Fall die Hexadezimalzahlen + \lstinline[style=terminal]{3b} und \lstinline[style=terminal]{29} + als Zeichen aus. Danach steht das String-Ende-Symbol mit Zahlenwert 0, + und die Ausgabe bricht ab. + Da, wie oben ermittelt, die Hexadezimalzahl \lstinline[style=terminal]{3b} + für das Zeichen \lstinline[style=terminal]{;} + und \lstinline[style=terminal]{29} + für das Zeichen \lstinline[style=terminal]{)} steht, + lautet somit die Ausgabe: + \begin{lstlisting}[style=terminal,gobble=8] + ;) + \end{lstlisting} + Um die Aufgabe zu lösen, können Sie übrigens auch + auf einem Little-Endian-Computer (Standard-Notebook) + einen Big-Endian-Computer simulieren, + indem Sie die Reihenfolge der Bytes in der Zahl \lstinline{x} umdrehen + -- siehe die Datei \gitfile{hp}{2021ws/20211129}{loesung-1-3.c}. + \end{itemize} + + \exercise{Thermometer-Baustein an \ITWOC-Bus} + + Eine Firma stellt einen elektronischen Thermometer-Baustein her, + den man über die serielle Schnittstelle (RS-232) an einen PC anschließen kann, + um die Temperatur auszulesen. + Nun wird eine Variante des Thermo"-meter-Bausteins entwickelt, + die die Temperatur zusätzlich über einen \ItwoC-Bus bereitstellt. + + Um das neue Thermometer zu testen, wird es in ein Gefäß mit heißem Wasser gelegt, + das langsam auf Zimmertemperatur abkühlt. + Alle 10 Minuten liest ein Programm, das auf dem PC läuft, + die gemessene Temperatur über beide Schnittstellen aus + und erzeugt daraus die folgende Tabelle: + + \begin{center} + \renewcommand{\arraystretch}{1.2} + \begin{tabular}{|c|c|c|}\hline + Zeit /\,min. & Temperatur per RS-232 /\,\degree C & Temperatur per \ItwoC\ /\,\degree C \\\hline\hline + \phantom{0}0 & 94 & 122 \\\hline + 10 & 47 & 244 \\\hline + 20 & 30 & 120 \\\hline + 30 & 24 & \phantom{0}24 \\\hline + 40 & 21 & 168 \\\hline + \end{tabular} + \end{center} + + \begin{itemize} + \item[(a)] + Aus dem Vergleich der Meßdaten läßt sich + auf einen Fehler bei der \ItwoC-Übertragung schließen.\\ + Um welchen Fehler handelt es sich, + und wie ergibt sich dies aus den Meßdaten? + \points{5} + \item[(b)] + Schreiben Sie eine C-Funktion \lstinline{uint8_t repair (uint8_t data)}, + die eine über den \ItwoC-Bus empfangene fehlerhafte Temperatur \lstinline{data} korrigiert. + \points{5} + \end{itemize} + + \solution + + \begin{itemize} + \item[(a)] + \textbf{Aus dem Vergleich der Meßdaten läßt sich + auf einen Fehler bei der \ItwoC-Übertragung schließen. + Um welchen Fehler handelt es sich, + und wie ergibt sich dies aus den Meßdaten?} + + Sowohl RS-232 als auch \ItwoC\ übertragen die Daten Bit für Bit. + Für die Fehlersuche ist es daher sinnvoll, + die Meßwerte als Binärzahlen zu betrachten: + + \begin{center} + \renewcommand{\arraystretch}{1.2} + \begin{tabular}{|c|c|c|}\hline + Zeit /\,min. & Temperatur per RS-232 /\,\degree C & Temperatur per \ItwoC\ /\,\degree C \\\hline\hline + \phantom{0}0 & 94$_{10}$ = 01011110$_2$ & 122$_{10}$ = 01111010$_2$ \\\hline + 10 & 47$_{10}$ = 00101111$_2$ & 244$_{10}$ = 11110100$_2$ \\\hline + 20 & 30$_{10}$ = 00011110$_2$ & 120$_{10}$ = 01111000$_2$ \\\hline + 30 & 24$_{10}$ = 00011000$_2$ & \phantom{0}24$_{10}$ = 00011000$_2$ \\\hline + 40 & 21$_{10}$ = 00010101$_2$ & 168$_{10}$ = 10101000$_2$ \\\hline + \end{tabular} + \end{center} + + Man erkennt, daß die Reihenfolge der Bits in den (fehlerhaften) \ItwoC-Meßwerten + genau die umgekehrte Reihenfolge der Bits in den (korrekten) RS-232-Mewßwerten ist. + Der Übertragungsfehler besteht also darin, + daß die Bits in der falschen Reihenfolge übertragen wurden. + + Dies paßt gut damit zusammen, + daß die Bit-Reihenfolge von \ItwoC\ \emph{MSB First}, die von RS-232 hingegen \emph{LSB First\/} ist. + Offenbar haben die Entwickler der \ItwoC-Schnittstelle dies übersehen + und die \ItwoC-Daten ebenfalls \emph{LSB First\/} übertragen. + + \goodbreak + \item[(b)] + \textbf{Schreiben Sie eine C-Funktion \lstinline{uint8_t repair (uint8_t data)}, + die eine über den \ItwoC-Bus empfangene fehlerhafte Temperatur \lstinline{data} korrigiert.} + + Die Aufgabe der Funktion besteht darin, + eine 8-Bit-Zahl \lstinline{data} entgegenzunehmen, + die Reihenfolge der 8 Bits genau umzudrehen + und das Ergebnis mittels \lstinline{return} zurückzugeben. + + Zu diesem Zweck gehen wir die 8 Bits in einer Schleife durch + -- siehe die Datei \gitfile{hp}{2021ws/20211129}{loesung-2.c}. + Wir lassen eine Lese-Maske \lstinline{mask_data} von rechts nach links + und gleichzeitig eine Schreib-Maske \lstinline{mask_result} + von links nach rechts wandern. + Immer wenn die Lese-Maske in \lstinline{data} eine 1 findet, + schreibt die Schreib-Maske diese in die Ergebnisvariable \lstinline{result}. + + Da \lstinline{result} auf 0 initialisiert wurde, + brauchen wir Nullen nicht hineinzuschreiben. + Ansonsten wäre dies mit \lstinline{result &= ~mask_result} möglich. + + Um die Schleife bis 8 zählen zu lassen, + könnte man eine weitere Zähler-Variable von 0 bis 7 zählen lassen, + z.\,B.\ \lstinline{for (int i = 0; i < 8; i++)}. + Dies ist jedoch nicht nötig, wenn man beachtet, + daß die Masken den Wert 0 annehmen, + sobald das Bit aus der 8-Bit-Variablen herausgeschoben wurde. + In \gitfile{hp}{2021ws/20211129}{loesung-2.c} wird \lstinline{mask_data} auf 0 geprüft; + genausogut könnte man auch \lstinline{mask_result} prüfen. + + Das \lstinline{return result} ist notwendig. + Eine Ausgabe des Ergebnisses per \lstinline{printf()} o.\,ä.\ + erfüllt \emph{nicht\/} die Aufgabenstellung. + (In \gitfile{hp}{2021ws/20211129}{loesung-2.c} erfolgt entsprechend \lstinline{printf()} + nur im Testprogramm \lstinline{main()}.) + \end{itemize} + + \exercise{Speicherformate von Zahlen} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211129}{aufgabe-3.c}): + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + + typedef struct + { + uint32_t a; + uint64_t b; + uint8_t c; + } three_numbers; + + int main (void) + { + three_numbers xyz = { 1819042120, 2410670883059281007, 0 }; + printf ("%s\n", &xyz); + return 0; + } + \end{lstlisting} + + Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\ + (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür, + daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.) + + \begin{lstlisting}[style=terminal] + $ ¡gcc -Wall -m32 aufgabe-2.c -o aufgabe-2¿ + aufgabe-2.c: In function "main": + aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", but + argument 2 has type "three_numbers * {aka struct <anonymous> *}" [-Wformat=] + printf ("%s\n", &xyz); + ^ + $ ¡./aufgabe-2¿ + Hallo, Welt! + \end{lstlisting} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie die beim Compilieren auftretende Warnung. + \points{2} + \item + Erklären Sie die Ausgabe des Programms. + \points{4} + \item + Welche Endianness hat der verwendete Rechner? + Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus? + \points{2} + \item + Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\ + (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür, + daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.) + \begin{lstlisting}[style=terminal,gobble=8] + $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿ + aufgabe-2.c: In function "main": + aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", + but argument 2 has type "three_numbers * {aka struct <anonymous> *}" + [-Wformat=] + printf ("%s\n", &xyz); + ^ + $ ¡./aufgabe-2¿ + Hall5V + \end{lstlisting} + (Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)\par + Erklären Sie die geänderte Ausgabe des Programms. + \points{3} + \end{enumerate} + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Erklären Sie die beim Compilieren auftretende Warnung.} + + Die Funktion \lstinline{printf()} mit der Formatspezifikation \lstinline{%s} + erwartet als Parameter einen String, d.\,h.\ einen Zeiger auf \lstinline{char}. + Die Adresse (\lstinline{&}) der Variablen \lstinline{xyz} + ist zwar ein Zeiger, aber nicht auf \lstinline{char}, + sondern auf einen \lstinline{struct} vom Typ \lstinline{three_numbers}. + Eine implizite Umwandlung des Zeigertyps ist zwar möglich, + aber normalerweise nicht das, was man beabsichtigt. + + \item + \textbf{Erklären Sie die Ausgabe des Programms.} + + Ein String in C ist ein Array von \lstinline{char}s + bzw.\ ein Zeiger auf \lstinline{char}. + Da die Funktion \lstinline{printf()} mit der Formatspezifikation \lstinline{%s} + einen String erwartet, wird sie das, worauf der übergebene Zeiger zeigt, + als ein Array von \lstinline{char}s interpretieren. + Ein \lstinline{char} entspricht einer 8-Bit-Speicherzelle. + Um die Ausgabe des Programms zu erklären, müssen wir daher + die Speicherung der Zahlen in den einzelnen 8-Bit-Speicherzellen betrachten. + + Hierfür wandeln wir zunächst die Zahlen von Dezimal nach Hexadezimal um. + Sofern nötig (hier nicht der Fall) füllen wir von links mit Nullen auf, + um den gesamten von der Variablen belegten Speicherplatz zu füllen + (hier: 32 Bit, 64 Bit, 8 Bit). + Jeweils 2 Hex-Ziffern stehen für 8 Bit. + \begin{center} + \begin{tabular}{rcl} + dezimal & & hexadezimal \\[\smallskipamount] + 1\,819\,042\,120 & = & 6C\,6C\,61\,48 \\ + 2\,410\,670\,883\,059\,281\,007 & = & 21\,74\,6C\,65\,57\,20\,2C\,6F \\ + 0 & = & 00 + \end{tabular} + \end{center} + Die Anordnung dieser 8-Bit-Zellen im Speicher lautet + \textbf{auf einem Big-Endian-Rechner} wie folgt: + \begin{center} + \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline + \raisebox{0.5ex}{\strut} + 6C & 6C & 61 & 48 & + 21 & 74 & 6C & 65 & 57 & 20 & 2C & 6F & + 00 + \\\hline + \end{tabular}\\[-4.2ex] + \kern1.7em% + $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt% + $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt% + $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$% + \end{center} + \textbf{Auf einem Little-Endian-Rechner} lautet sie hingegen: + \begin{center} + \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline +% \raisebox{0.5ex}{\strut} +% H & a & l & l & +% o & , & & W & e & l & t & ! & \\\hline + \raisebox{0.5ex}{\strut} + 48 & 61 & 6C & 6C & + 6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 & + 00 + \\\hline + \end{tabular}\\[-4.2ex] + \kern1.7em% + $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt% + $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt% + $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$% + \end{center} + Anhand einer ASCII-Tabelle erkennt man, + daß die Big-Endian-Variante dem String \lstinline{"llaH!tleW ,o"} + und die Little-Endian-Variante dem String \lstinline{"Hallo, Welt!"} + entspricht -- jeweils mit einem Null-Symbol am Ende, + das von der Variablen \lstinline{c} herrührt. + + Auf einem Little-Endian-Rechner wird daher + \lstinline[style=terminal]{Hallo, Welt!} ausgegeben. + + \item + \textbf{Welche Endianness hat der verwendete Rechner?} + + Little-Endian (Begründung siehe oben) + + \textbf{Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus?} + + \lstinline[style=terminal]{llaH!tleW ,o} (Begründung siehe oben) + + \item + \textbf{Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\ + (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür, + daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.)} + \begin{lstlisting}[style=terminal,gobble=8] + $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿ + aufgabe-2.c: In function "main": + aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", + but argument 2 has type "three_numbers * {aka struct <anonymous> *}" + [-Wformat=] + printf ("%s\n", &xyz); + ^ + $ ¡./aufgabe-2¿ + Hall5V + \end{lstlisting} + \textbf{(Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)}\par + \textbf{Erklären Sie die geänderte Ausgabe des Programms.} + + \goodbreak + + Auf einem 64-Bit-Rechner hat eine 64-Bit-Variable + ein \textbf{64-Bit-Alignment}, + d.\,h.\ ihre Speicheradresse muß durch 8 teilbar sein. + + Der Compiler legt die Variablen daher wie folgt im Speicher ab (Little-Endian): + \begin{center} + \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline + \raisebox{0.5ex}{\strut} + 48 & 61 & 6C & 6C & ?? & ?? & ?? & ?? & + 6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 & + 00 + \\\hline + \end{tabular}\\[-4.2ex] + \kern1.7em% + $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt% + $\underbrace{\rule{9.1em}{0pt}}_{\mbox{Füll-Bytes}}$\kern1pt% + $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt% + $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$% + \end{center} + Der Inhalt der Füll-Bytes ist undefiniert. + Im Beispiel aus der Aufgabenstellung entsteht hier die Ausgabe + \lstinline[style=terminal]{5V}, was den (zufälligen) hexadezimalen Werten + 35 56 entspricht: + \begin{center} + \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}\hline + \raisebox{0.5ex}{\strut} + 48 & 61 & 6C & 6C & 35 & 56 & 00 & ?? & + 6F & 2C & 20 & 57 & 65 & 6C & 74 & 21 & + 00 + \\\hline + \end{tabular}\\[-4.2ex] + \kern1.7em% + $\underbrace{\rule{9.8em}{0pt}}_{\mbox{\lstinline{a}}}$\kern1pt% + $\underbrace{\rule{9.1em}{0pt}}_{\mbox{Füll-Bytes}}$\kern1pt% + $\underbrace{\rule{18.8em}{0pt}}_{\mbox{\lstinline{b}}}$\kern1pt% + $\underbrace{\rule{2.2em}{0pt}}_{\mbox{\lstinline{c}}}$% + \end{center} + Da danach die Ausgabe aufhört, muß an der nächsten Stelle + ein Null-Symbol stehen, das das Ende des Strings anzeigt. + Der Inhalt der darauf folgenden Speicherzelle bleibt unbekannt. + \end{enumerate} + +\end{document} diff --git a/20211129/hp-uebung-20211129.pdf b/20211129/hp-uebung-20211129.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b88e4a195ecefd36fe9bf24f73f0f1e8828a5fa7 Binary files /dev/null and b/20211129/hp-uebung-20211129.pdf differ diff --git a/20211129/hp-uebung-20211129.tex b/20211129/hp-uebung-20211129.tex new file mode 100644 index 0000000000000000000000000000000000000000..687eb8f6b544b1bf4cb01eff3558376b4d6d008f --- /dev/null +++ b/20211129/hp-uebung-20211129.tex @@ -0,0 +1,195 @@ +% hp-uebung-20211122.pdf - Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Trickprogrammierung, Thermometer-Baustein an I²C-Bus + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{gensymb} + +\newcommand{\ItwoC}{I\raisebox{0.5ex}{\footnotesize 2}C} +\newcommand{\ITWOC}{I\raisebox{0.5ex}{\normalsize 2}C} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 22.\ November 2021} + + Diese Übung enthält Punkteangaben wie in einer Klausur. + Um zu "`bestehen"', müssen Sie innerhalb von 90 Minuten + unter Verwendung ausschließlich zugelassener Hilfsmittel + 15 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Trickprogrammierung} + + Wir betrachten das folgende Programm (Datei: \gitfile{hp}{2021ws/20211129}{aufgabe-1.c}): + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + + int main (void) + { + uint64_t x = 4262939000843297096; + char *s = &x; + printf ("%s\n", s); + return 0; + } + \end{lstlisting} + Das Programm wird compiliert und auf einem 64-Bit-Little-Endian-Computer ausgeführt: + \begin{lstlisting}[style=terminal] + $ ¡gcc -Wall -O aufgabe-1.c -o aufgabe-1¿ + aufgabe-1.c: In function `main': + aufgabe-1.c:7:13: warning: initialization from incompatible pointer type [...] + $ ¡./aufgabe-1¿ + Hallo + \end{lstlisting} + + \begin{itemize} + \item[(a)] + Erklären Sie die Warnung beim Compilieren. \points{2} + \item[(b)] + Erklären Sie die Ausgabe des Programms. \points{5} + \item[(c)] + Wie würde die Ausgabe des Programms auf einem 64-Bit-Big-Endian-Computer lauten? \points{3} + \end{itemize} + Hinweis: Modifizieren Sie das Programm + und lassen Sie sich Speicherinhalte ausgeben. + + \exercise{Thermometer-Baustein an \ITWOC-Bus} + + Eine Firma stellt einen elektronischen Thermometer-Baustein her, + den man über die serielle Schnittstelle (RS-232) an einen PC anschließen kann, + um die Temperatur auszulesen. + Nun wird eine Variante des Thermo"-meter-Bausteins entwickelt, + die die Temperatur zusätzlich über einen \ItwoC-Bus bereitstellt. + + Um das neue Thermometer zu testen, wird es in ein Gefäß mit heißem Wasser gelegt, + das langsam auf Zimmertemperatur abkühlt. + Alle 10 Minuten liest ein Programm, das auf dem PC läuft, + die gemessene Temperatur über beide Schnittstellen aus + und erzeugt daraus die folgende Tabelle: + + \begin{center} + \renewcommand{\arraystretch}{1.2} + \begin{tabular}{|c|c|c|}\hline + Zeit /\,min. & Temperatur per RS-232 /\,\degree C & Temperatur per \ItwoC\ /\,\degree C \\\hline\hline + \phantom{0}0 & 94 & 122 \\\hline + 10 & 47 & 244 \\\hline + 20 & 30 & 120 \\\hline + 30 & 24 & \phantom{0}24 \\\hline + 40 & 21 & 168 \\\hline + \end{tabular} + \end{center} + + \begin{itemize} + \item[(a)] + Aus dem Vergleich der Meßdaten läßt sich + auf einen Fehler bei der \ItwoC-Übertragung schließen.\\ + Um welchen Fehler handelt es sich, + und wie ergibt sich dies aus den Meßdaten? + \points{5} + \item[(b)] + Schreiben Sie eine C-Funktion \lstinline{uint8_t repair (uint8_t data)}, + die eine über den \ItwoC-Bus empfangene fehlerhafte Temperatur \lstinline{data} korrigiert. + \points{5} + \end{itemize} + + \exercise{Speicherformate von Zahlen} + + Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211129}{aufgabe-3.c}): + \begin{lstlisting} + #include <stdio.h> + #include <stdint.h> + + typedef struct + { + uint32_t a; + uint64_t b; + uint8_t c; + } three_numbers; + + int main (void) + { + three_numbers xyz = { 1819042120, 2410670883059281007, 0 }; + printf ("%s\n", &xyz); + return 0; + } + \end{lstlisting} + + Das Programm wird für einen 32-Bit-Rechner compiliert und ausgeführt.\\ + (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m32} sorgt dafür, + daß \lstinline[style=cmd]{gcc} Code für einen 32-Bit-Prozessor erzeugt.) + + \begin{lstlisting}[style=terminal] + $ ¡gcc -Wall -m32 aufgabe-2.c -o aufgabe-2¿ + aufgabe-2.c: In function "main": + aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", but + argument 2 has type "three_numbers * {aka struct <anonymous> *}" [-Wformat=] + printf ("%s\n", &xyz); + ^ + $ ¡./aufgabe-2¿ + Hallo, Welt! + \end{lstlisting} + + \begin{enumerate}[\quad(a)] + \item + Erklären Sie die beim Compilieren auftretende Warnung. + \points{2} + \item + Erklären Sie die Ausgabe des Programms. + \points{4} + \item + Welche Endianness hat der verwendete Rechner? + Wie sähe die Ausgabe auf einem Rechner mit entgegengesetzter Endianness aus? + \points{2} + \item + Dasselbe Programm wird nun für einen 64-Bit-Rechner compiliert und ausgeführt.\\ + (Die \lstinline[style=cmd]{gcc}-Option \lstinline[style=cmd]{-m64} sorgt dafür, + daß \lstinline[style=cmd]{gcc} Code für einen 64-Bit-Prozessor erzeugt.) + \begin{lstlisting}[style=terminal,gobble=8] + $ ¡gcc -Wall -m64 aufgabe-2.c -o aufgabe-2¿ + aufgabe-2.c: In function "main": + aufgabe-2.c:14:13: warning: format "%s" expects argument of type "char *", + but argument 2 has type "three_numbers * {aka struct <anonymous> *}" + [-Wformat=] + printf ("%s\n", &xyz); + ^ + $ ¡./aufgabe-2¿ + Hall5V + \end{lstlisting} + (Es ist möglich, daß die konkrete Ausgabe auf Ihrem Rechner anders aussieht.)\par + Erklären Sie die geänderte Ausgabe des Programms. + \points{3} + \end{enumerate} + + \begin{flushright} + \textit{Viel Erfolg!} + \end{flushright} + + \makeatletter + \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} + \makeatother + +\end{document} diff --git a/20211129/io-ports-and-interrupts.pdf b/20211129/io-ports-and-interrupts.pdf new file mode 120000 index 0000000000000000000000000000000000000000..bcd46f7afb35605b20bdb05637e6de0a039893ec --- /dev/null +++ b/20211129/io-ports-and-interrupts.pdf @@ -0,0 +1 @@ +../common/io-ports-and-interrupts.pdf \ No newline at end of file diff --git a/20211129/loesung-1-1.c b/20211129/loesung-1-1.c new file mode 100644 index 0000000000000000000000000000000000000000..26fcc817796b3da118b5dda92f45bfb870e315b6 --- /dev/null +++ b/20211129/loesung-1-1.c @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +int main (void) +{ + uint64_t x = 4262939000843297096; + char *s = &x; + printf ("%lx\n", x); + printf ("%" PRIx64 "\n", x); + printf ("%s\n", s); + return 0; +} diff --git a/20211129/loesung-1-2.c b/20211129/loesung-1-2.c new file mode 100644 index 0000000000000000000000000000000000000000..7151db69b2e675f17517d7b7c3814bbda3b1fa89 --- /dev/null +++ b/20211129/loesung-1-2.c @@ -0,0 +1,15 @@ +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +int main (void) +{ + uint64_t x = 4262939000843297096; + char *s = &x; + printf ("%lx\n", x); + printf ("%" PRIx64 "\n", x); + printf ("%c %c %c %c %c %c %c %c\n", + 0x48, 0x61, 0x6c, 0x6c, 0x6f, 0x00, 0x29, 0x3b); + printf ("%s\n", s); + return 0; +} diff --git a/20211129/loesung-1-3.c b/20211129/loesung-1-3.c new file mode 100644 index 0000000000000000000000000000000000000000..fadccdef1155e4d16b5da0c8a82d8e7ae76ca3cc --- /dev/null +++ b/20211129/loesung-1-3.c @@ -0,0 +1,11 @@ +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +int main (void) +{ + uint64_t x = 0x48616c6c6f00293b; + char *s = &x; + printf ("%s\n", s); + return 0; +} diff --git a/20211129/loesung-2.c b/20211129/loesung-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b02d98b51b9bc525a567afea2f0dce5a8e6413a5 --- /dev/null +++ b/20211129/loesung-2.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <stdint.h> + +uint8_t repair (uint8_t data) +{ + uint8_t result = 0; + uint8_t mask_data = 0x01; + uint8_t mask_result = 0x80; + while (mask_data) + { + if (data & mask_data) + result |= mask_result; + mask_data <<= 1; + mask_result >>= 1; + } + return result; +} + +int main (void) +{ + int data[] = { 122, 244, 120, 24, 168, -1 }; + int i = 0; + while (data[i] >= 0) + printf ("%d\n", repair (data[i++])); + return 0; +} diff --git a/20211129/logo-hochschule-bochum-cvh-text-v2.pdf b/20211129/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20211129/logo-hochschule-bochum-cvh-text-v2.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum-cvh-text-v2.pdf \ No newline at end of file diff --git a/20211129/logo-hochschule-bochum.pdf b/20211129/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20211129/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20211129/pendulum-0.c b/20211129/pendulum-0.c new file mode 100644 index 0000000000000000000000000000000000000000..6faebdc7ad779d89ab8e2eacd189240ace1fb406 --- /dev/null +++ b/20211129/pendulum-0.c @@ -0,0 +1,69 @@ +#include <gtk/gtk.h> +#include <math.h> + +int width = 320; +int height = 240; +int gap = height / 20; +int r = gap; +double visual_length = height - 2 * gap - r; + +double phi0 = -0.5; +double omega0 = 0.0; +double t0 = 0.0; +double g = 9.81; +double l = 1.0; +double dt = 0.02; + +double t = t0; +double phi = phi0; +double omega = omega0; + +gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) +{ + GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 }; + + int x = width / 2 + visual_length * sin (phi); + int y = gap + visual_length * cos (phi); + + gdk_cairo_set_source_rgba (c, &blue); + cairo_move_to (c, width / 2, gap); + cairo_line_to (c, x, y); + cairo_stroke (c); + cairo_arc (c, x, y, r, 0, 2 * G_PI); + cairo_fill (c); + + return FALSE; /* TRUE to stop other handlers from being invoked for the event. + FALSE to propagate the event further. */ +} + +gboolean timer (GtkWidget *widget) +{ + t += dt; + phi += omega * dt; + omega += - dt * g / l * sin (phi); + + gtk_widget_queue_draw_area (widget, 0, 0, width, height); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_show (window); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + GtkWidget *drawing_area = gtk_drawing_area_new (); + gtk_widget_show (drawing_area); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + gtk_widget_set_size_request (drawing_area, width, height); + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + + gtk_main (); + return 0; +} diff --git a/20211129/pendulum-1.c b/20211129/pendulum-1.c new file mode 100644 index 0000000000000000000000000000000000000000..44f4c4fde79d96ed604882b0d5ce22a9035e1400 --- /dev/null +++ b/20211129/pendulum-1.c @@ -0,0 +1,69 @@ +#include <gtk/gtk.h> +#include <math.h> + +#define WIDTH 320 +#define HEIGHT 240 +#define GAP (HEIGHT / 20) +#define r GAP +#define visual_length (HEIGHT - 2 * GAP - r) + +#define phi0 (-0.5) +#define omega0 0.0 +#define t0 0.0 +#define g 9.81 +#define l 1.0 +#define dt 0.02 + +double t = t0; +double phi = phi0; +double omega = omega0; + +gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) +{ + GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 }; + + int x = WIDTH / 2 + visual_length * sin (phi); + int y = GAP + visual_length * cos (phi); + + gdk_cairo_set_source_rgba (c, &blue); + cairo_move_to (c, WIDTH / 2, 10); + cairo_line_to (c, x, y); + cairo_stroke (c); + cairo_arc (c, x, y, r, 0, 2 * G_PI); + cairo_fill (c); + + return FALSE; /* TRUE to stop other handlers from being invoked for the event. + FALSE to propagate the event further. */ +} + +gboolean timer (GtkWidget *widget) +{ + t += dt; + phi += omega * dt; + omega += - dt * g / l * sin (phi); + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_show (window); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + GtkWidget *drawing_area = gtk_drawing_area_new (); + gtk_widget_show (drawing_area); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT); + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + + gtk_main (); + return 0; +} diff --git a/20211129/pendulum-2.c b/20211129/pendulum-2.c new file mode 100644 index 0000000000000000000000000000000000000000..4fbad9a50cc595e92fbb1075dd01405a08e84001 --- /dev/null +++ b/20211129/pendulum-2.c @@ -0,0 +1,69 @@ +#include <gtk/gtk.h> +#include <math.h> + +#define WIDTH 320 +#define HEIGHT 240 +#define GAP (HEIGHT / 20) +#define r GAP +#define visual_length (HEIGHT - 2 * GAP - r) + +#define phi0 (-0.5) +#define omega0 0.0 +#define t0 0.0 +#define g 9.81 +#define l 1.0 +#define dt 0.02 + +double t = t0; +double phi = phi0; +double omega = omega0; + +gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) +{ + GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 }; + + int x = WIDTH / 2 + visual_length * sin (phi); + int y = GAP + visual_length * cos (phi); + + gdk_cairo_set_source_rgba (c, &orange); + cairo_move_to (c, WIDTH / 2, 10); + cairo_line_to (c, x, y); + cairo_stroke (c); + cairo_arc (c, x, y, r, 0, 2 * G_PI); + cairo_fill (c); + + return FALSE; /* TRUE to stop other handlers from being invoked for the event. + FALSE to propagate the event further. */ +} + +gboolean timer (GtkWidget *widget) +{ + t += dt; + phi += omega * dt; + omega += - dt * g / l * phi; + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_show (window); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + GtkWidget *drawing_area = gtk_drawing_area_new (); + gtk_widget_show (drawing_area); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT); + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + + gtk_main (); + return 0; +} diff --git a/20211129/pendulum-3.c b/20211129/pendulum-3.c new file mode 100644 index 0000000000000000000000000000000000000000..35b0b67aeb0d11aa2a81aba204c97ca96504ad89 --- /dev/null +++ b/20211129/pendulum-3.c @@ -0,0 +1,86 @@ +#include <gtk/gtk.h> +#include <math.h> + +#define WIDTH 320 +#define HEIGHT 240 +#define GAP (HEIGHT / 20) +#define r GAP +#define visual_length (HEIGHT - 2 * GAP - r) + +#define phi0 (-0.5) +#define omega0 0.0 +#define t0 0.0 +#define g 9.81 +#define l 1.0 +#define dt 0.02 + +double t = t0; +double phi_with_sin = phi0; +double omega_with_sin= omega0; +double phi_without_sin = phi0; +double omega_without_sin= omega0; + +void draw_pendulum (cairo_t *c, double phi, GdkRGBA *colour) +{ + int x = WIDTH / 2 + visual_length * sin (phi); + int y = GAP + visual_length * cos (phi); + + gdk_cairo_set_source_rgba (c, colour); + cairo_move_to (c, WIDTH / 2, 10); + cairo_line_to (c, x, y); + cairo_stroke (c); + cairo_arc (c, x, y, r, 0, 2 * G_PI); + cairo_fill (c); +} + +gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) +{ + GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 }; + GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 }; + GdkRGBA green = { 0.0, 0.5, 0.0, 1.0 }; + + double A = phi0; + double B = 0.5 * M_PI; /* 90° */ + double phi_analytic = A * sin (sqrt (g / l) * t + B); + + draw_pendulum (c, phi_with_sin, &blue); + draw_pendulum (c, phi_without_sin, &orange); + draw_pendulum (c, phi_analytic, &green); + + return FALSE; /* TRUE to stop other handlers from being invoked for the event. + FALSE to propagate the event further. */ +} + +gboolean timer (GtkWidget *widget) +{ + t += dt; + phi_with_sin += omega_with_sin * dt; + omega_with_sin += - dt * g / l * sin (phi_with_sin); + phi_without_sin += omega_without_sin * dt; + omega_without_sin += - dt * g / l * phi_without_sin; + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_show (window); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + GtkWidget *drawing_area = gtk_drawing_area_new (); + gtk_widget_show (drawing_area); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT); + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + + gtk_main (); + return 0; +} diff --git a/20211129/pendulum-4.c b/20211129/pendulum-4.c new file mode 100644 index 0000000000000000000000000000000000000000..1a08e32735336064af72ce6f332299d14ff66218 --- /dev/null +++ b/20211129/pendulum-4.c @@ -0,0 +1,86 @@ +#include <gtk/gtk.h> +#include <math.h> + +#define WIDTH 320 +#define HEIGHT 240 +#define GAP (HEIGHT / 20) +#define r GAP +#define visual_length (HEIGHT - 2 * GAP - r) + +#define phi0 (-5.0 / 180.0 * M_PI) +#define omega0 0.0 +#define t0 0.0 +#define g 9.81 +#define l 1.0 +#define dt 0.02 + +double t = t0; +double phi_with_sin = phi0; +double omega_with_sin= omega0; +double phi_without_sin = phi0; +double omega_without_sin= omega0; + +void draw_pendulum (cairo_t *c, double phi, GdkRGBA *colour) +{ + int x = WIDTH / 2 + visual_length * sin (phi); + int y = GAP + visual_length * cos (phi); + + gdk_cairo_set_source_rgba (c, colour); + cairo_move_to (c, WIDTH / 2, 10); + cairo_line_to (c, x, y); + cairo_stroke (c); + cairo_arc (c, x, y, r, 0, 2 * G_PI); + cairo_fill (c); +} + +gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data) +{ + GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 }; + GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 }; + GdkRGBA green = { 0.0, 0.5, 0.0, 1.0 }; + + double A = phi0; + double B = 0.5 * M_PI; /* 90° */ + double phi_analytic = A * sin (sqrt (g / l) * t + B); + + draw_pendulum (c, phi_with_sin, &blue); + draw_pendulum (c, phi_without_sin, &orange); + draw_pendulum (c, phi_analytic, &green); + + return FALSE; /* TRUE to stop other handlers from being invoked for the event. + FALSE to propagate the event further. */ +} + +gboolean timer (GtkWidget *widget) +{ + t += dt; + phi_with_sin += omega_with_sin * dt; + omega_with_sin += - dt * g / l * sin (phi_with_sin); + phi_without_sin += omega_without_sin * dt; + omega_without_sin += - dt * g / l * phi_without_sin; + + gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT); + g_timeout_add (50, (GSourceFunc) timer, widget); + return FALSE; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_show (window); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + + GtkWidget *drawing_area = gtk_drawing_area_new (); + gtk_widget_show (drawing_area); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT); + g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL); + + g_timeout_add (50, (GSourceFunc) timer, drawing_area); + + gtk_main (); + return 0; +} diff --git a/20211129/pendulum.pdf b/20211129/pendulum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..7d1d87305cdb8840a248ff2207538d758464f452 --- /dev/null +++ b/20211129/pendulum.pdf @@ -0,0 +1 @@ +../common/pendulum.pdf \ No newline at end of file diff --git a/20211129/pgscript.sty b/20211129/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20211129/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20211129/pgslides.sty b/20211129/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20211129/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file