diff --git a/20230515/bs-20230515.txt b/20230515/bs-20230515.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8f14e3a364f0602129f111d4feae6f83d446d36f
--- /dev/null
+++ b/20230515/bs-20230515.txt
@@ -0,0 +1,294 @@
+Von "Hello, world!n" bis zum Kernel, 15.05.2023, 16:20:31
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+printf ("Hello, world!\n"); wird zu puts ("Hello, world!"); optimiert.
+
+Quelltext von puts(): apt-get source glibc
+
+cassini/home/peter/bo/2023ss/bs/20230515/glibc-2.28> find . -name "*puts*.c"
+./gshadow/putsgent.c
+./gshadow/tst-putsgent.c
+./libio/iofputs.c
+./libio/iofputs_u.c
+./libio/ioputs.c
+...
+
+int _IO_puts (const char *str)
+
+weak_alias (_IO_puts, puts)
+
+--> Information für den Linker:
+    Wenn ein Benutzerprogramm nach "puts()" fragt, gib ihm "_IO_puts()".
+
+include/libc-symbols.h:
+
+  /* Define ALIASNAME as a weak alias for NAME.
+     If weak aliases are not available, this defines a strong alias.  */
+  # define weak_alias(name, aliasname) _weak_alias (name, aliasname)
+  # define _weak_alias(name, aliasname) \
+    extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
+
+  "__attribute__ (( ... ));" ist ein spezieller GCC-Befehl.
+  Warum 2 Klammern auf und zu?
+  Wenn ein anderer Compiler diesen Befehl nicht kennt, machen wir:
+    #define __attribute__ (X)
+  Mit nur einem Klammerpaar müßten wir zwischen
+    #define __attribute__ (X)
+    #define __attribute__ (X,Y)
+    #define __attribute__ (X,Y,Z)
+  unterscheiden. Der Präprozessor kennt aber nur eine feste Anzahl von Parametern.
+
+Warum "weak_alias"?
+--> Vermeidung von Namenskonflikten.
+    Wenn das Benutzerprogramm selbst eine Funktion puts() bereitstellt,
+    hat diese Vorrang vor der in der glibc.
+
+puts() ruft _IO_sputn() auf.
+
+_IO_sputn() ist ein Makro:
+
+  libio/libioP.h:
+  #define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
+
+Dies ist wahrscheinlich ein "Hook": Durch Umdefinieren des Makros
+kann man auf einfache Weise die Funktion auf eine andere "umleiten".
+
+Dieser ruft einen weiteren Makro auf:
+
+  libio/libioP.h:
+  #define _IO_XSPUTN(FP, DATA, N) JUMP2 (__xsputn, FP, DATA, N)
+
+Dieser ruft einen weiteren Makro auf:
+
+  libio/libioP.h:
+  #define JUMP2(FUNC, THIS, X1, X2) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS, X1, X2)
+
+Dieser ruft eine Funktion auf, verwendet dabei einen weiteren Makro:
+
+  libio/libioP.h:
+  # define _IO_JUMPS_FUNC(THIS) \
+    (IO_validate_vtable                                                   \
+     (*(struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus (THIS)       \
+                               + (THIS)->_vtable_offset)))
+
+"vtable" ist eine virtuelle Methodentabelle.
+_IO_puts() ist eine "Methode" der Datei (hier: stdout).
+
+Vor dem Aufruf der Methode macht glibc eine Laufzeitüberprüfung der
+virtuellen Methodentabelle.
+
+libio/libioP.h enthält eine Typendeklaration struct _IO_jump_t
+
+grep -ir " _IO_jump_t" *
+libio/fileops.c:
+
+  const struct _IO_jump_t _IO_file_jumps libio_vtable =
+  {
+    /* Inhalt der vtable ... */
+    ...
+    JUMP_INIT(overflow, _IO_file_overflow),
+    ...
+    JUMP_INIT(xsputn, _IO_file_xsputn),
+    ...
+    JUMP_INIT(write, _IO_new_file_write),
+    ...
+  }
+
+Funktion:
+
+  size_t
+  _IO_new_file_xsputn (FILE *f, const void *data, size_t n)
+  {
+    ...
+  }
+  libc_hidden_ver (_IO_new_file_xsputn, _IO_file_xsputn)
+
+Diese ruft gegen Ende eine weitere Funktion auf:
+
+  _IO_default_xsputn()
+
+libio/genops.c:
+
+  _IO_default_xsputn (FILE *f, const void *data, size_t n)
+
+Diese ruft u.a. einen Makro _IO_OVERFLOW auf.
+Dort erfolgt das eigentliche Schreiben.
+
+libio/libioP.h:
+
+  #define _IO_OVERFLOW(FP, CH) JUMP1 (__overflow, FP, CH)
+
+Dies ist also wieder der Aufruf einer virtuellen Methode.
+
+libio/genops.c:
+
+  int
+  _IO_new_file_overflow (FILE *f, int ch)
+  {
+    ...
+  }
+  libc_hidden_ver (_IO_new_file_overflow, _IO_file_overflow)
+
+Diese ruft u.a. _IO_do_write() auf.
+Dort erfolgt das eigentliche Schreiben.
+
+libio/genops.c:
+
+  versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
+
+  int
+  _IO_new_do_write (FILE *fp, const char *data, size_t to_do)
+  {
+    return (to_do == 0
+            || (size_t) new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
+  }
+  libc_hidden_ver (_IO_new_do_write, _IO_do_write)
+
+  static size_t
+  new_do_write (FILE *fp, const char *data, size_t to_do)
+  {
+    size_t count;
+    if (fp->_flags & _IO_IS_APPENDING)
+      /* On a system without a proper O_APPEND implementation,
+         you would need to sys_seek(0, SEEK_END) here, but is
+         not needed nor desirable for Unix- or Posix-like systems.
+         Instead, just indicate that offset (before and after) is
+         unpredictable. */
+      fp->_offset = _IO_pos_BAD;
+    else if (fp->_IO_read_end != fp->_IO_write_base)
+      {
+        off64_t new_pos
+          = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
+        if (new_pos == _IO_pos_BAD)
+          return 0;
+        fp->_offset = new_pos;
+      }
+    count = _IO_SYSWRITE (fp, data, to_do);
+    if (fp->_cur_column && count)
+      fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
+    _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
+    fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
+    fp->_IO_write_end = (fp->_mode <= 0
+                         && (fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
+                         ? fp->_IO_buf_base : fp->_IO_buf_end);
+    return count;
+  }
+
+new_do_write() ruft u.a. _IO_SYSWRITE() auf.
+Dort erfolgt das eigentliche Schreiben.
+
+libio/libioP.h:
+
+  #define _IO_SYSWRITE(FP, DATA, LEN) JUMP2 (__write, FP, DATA, LEN)
+
+libio/fileops.h:
+
+  ssize_t
+  _IO_new_file_write (FILE *f, const void *data, ssize_t n)
+  {
+    ssize_t to_do = n;
+    while (to_do > 0)
+      {
+        ssize_t count = (__builtin_expect (f->_flags2
+                                           & _IO_FLAGS2_NOTCANCEL, 0)
+                             ? __write_nocancel (f->_fileno, data, to_do)
+                             : __write (f->_fileno, data, to_do));
+        if (count < 0)
+          {
+            f->_flags |= _IO_ERR_SEEN;
+            break;
+          }
+        to_do -= count;
+        data = (void *) ((char *) data + count);
+      }
+    n -= to_do;
+    if (f->_offset >= 0)
+      f->_offset += n;
+    return n;
+  }
+
+grep -r __write * liefert sehr viele Implementationen von __write()
+für verschiedenste Unix-Kernel (u.a. Hurd, linux, ...).
+--> Ab jetzt ist der Quelltext plattformabhängig.
+
+sysdeps/unix/sysv/linux/write.c:
+
+  ssize_t
+  __libc_write (int fd, const void *buf, size_t nbytes)
+  {
+    return SYSCALL_CANCEL (write, fd, buf, nbytes);
+  }
+  libc_hidden_def (__libc_write)
+
+  weak_alias (__libc_write, __write)
+
+sysdeps/unix/sysdep.h:
+
+  #define SYSCALL_CANCEL(...) \
+    ({                                                                         \
+      long int sc_ret;                                                         \
+      if (SINGLE_THREAD_P)                                                     \
+        sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__);                            \
+      else                                                                     \
+        {                                                                      \
+          int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();                        \
+          sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__);                          \
+          LIBC_CANCEL_RESET (sc_cancel_oldtype);                               \
+        }                                                                      \
+      sc_ret;                                                                  \
+    })
+
+  #define INLINE_SYSCALL_CALL(...) \
+    __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
+
+  #define __INLINE_SYSCALL_DISP(b,...) \
+    __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+Der Parameter "b" ist "__INLINE_SYSCALL". Dieser ist neu hinzugekommen.
+Wir rufen demnach "__INLINE_SYSCALL<n>" auf, wobei <n> für die Anzahl der
+Parameter des Syscalls steht.
+
+  #define __INLINE_SYSCALL0(name) \
+    INLINE_SYSCALL (name, 0)
+  #define __INLINE_SYSCALL1(name, a1) \
+    INLINE_SYSCALL (name, 1, a1)
+  #define __INLINE_SYSCALL2(name, a1, a2) \
+    INLINE_SYSCALL (name, 2, a1, a2)
+  ...
+
+  #ifndef INLINE_SYSCALL
+  #define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args)
+  #endif
+
+--> Hier erfolgt der Aufruf der Funktion __syscall_write (fd, buf, nbytes).
+
+sysdeps/unix/syscalls.list: Liste aller Systemaufrufe mit Namen, Parametern
+  sowie dem Namen der Funktion innerhalb der glibc.
+  Daraus werden dann automatisch die Funktionen generiert.
+
+sysdeps/unix/sysv/linux/x86_64/syscall.S
+  enthält ein Assembler-Template (".S" steht für Assembler mit Präprozessor)
+  für den eigentlichen Funktionsaufruf.
+  Hier also:
+
+  __syscall_write (fd, buf, nbytes)
+
+    %rdi: Nummer des Syscalls (hier: 1(?) für "write")
+    %rsi, %rdx, %rcx, ...: Parameter des Syscalls (hier: fd, buf, nbytes)
+
+    syscall: ein spezieller Assembler-Befehl für den Aufruf einer Funktion im Kernel
+    --> Hardware-Unterstützung für den Übergang Kernel<-->Userspace
+    (früher auf x86-Prozessoren ab dem i386: Software-Interrupt 0x80)
+
+    Rückgabewert des Syscalls: %rax
+
+    cmpq $-4095, %rax       /* Check %rax for error.  */
+    jae SYSCALL_ERROR_LABEL /* Jump to error handler if error.  */
+
+    Der Sprung erfolgt, wenn %rax zwischen (einschließlich) -1 und -4095 liegt.
+    Siehe: https://stackoverflow.com/questions/21440403/what-does-the-cmpq-instruction-do
+
+Vorschlag für die verbleibende Zeit der heutigen Lehrveranstaltung:
+
+  Einblick in die Benutzung eines Debuggers
+  anhand eines einfachen Programms.
+  "Nicht so etwas Schwieriges wie 'Hello, world!'" (ME)
diff --git a/20230515/demo-01.c b/20230515/demo-01.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c81d82adc36a5c67e1c590ef57f0faeb561a449
--- /dev/null
+++ b/20230515/demo-01.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int main (void)
+{
+  for (int i = 10; i > 0; i--)
+    printf ("%d ... ", i);
+  printf ("Bumm.\n");
+  return 0;
+}
diff --git a/20230515/demo-02.c b/20230515/demo-02.c
new file mode 100644
index 0000000000000000000000000000000000000000..8f9923b2590e0a76fe2d09f4529ce2fe8be3d1fe
--- /dev/null
+++ b/20230515/demo-02.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+int main (void)
+{
+  for (int i = 10; i > 0; i--)
+    {
+      printf ("%d ... ", i);
+      fflush (stdout);
+    }
+  printf ("Bumm.\n");
+  return 0;
+}
diff --git a/20230515/demo-03.c b/20230515/demo-03.c
new file mode 100644
index 0000000000000000000000000000000000000000..0fc787aa4489e36ab7d3bb19814212474958cb13
--- /dev/null
+++ b/20230515/demo-03.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int main (void)
+{
+  for (int i = 10; i > 0; i--)
+    printf (i, " ... ");
+  printf ("Bumm.\n");
+  return 0;
+}
diff --git a/20230515/dev-chardev-01.txt b/20230515/dev-chardev-01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e2f946dad66415deea09930b0a473910e3d12fde
--- /dev/null
+++ b/20230515/dev-chardev-01.txt
@@ -0,0 +1,17 @@
+cassini/home/peter/bo/2023ss/bs/20230424> ls -l /dev/chardev
+crw-rw-rw- 1 root root 241, 0 Apr 24 18:31 /dev/chardev
+cassini/home/peter/bo/2023ss/bs/20230424> cat /dev/chardev
+I already told you 10 times Hello world!
+cassini/home/peter/bo/2023ss/bs/20230424> ls -l dev
+insgesamt 0
+crw-r--r-- 1 root root 241, 0 Apr 24 17:16 chardev
+cassini/home/peter/bo/2023ss/bs/20230424> cat dev/chardev
+I already told you 11 times Hello world!
+cassini/home/peter/bo/2023ss/bs/20230424> mkdir -p ../20230515/dev
+cassini/home/peter/bo/2023ss/bs/20230424> touch ../20230515/dev/chardev
+cassini/home/peter/bo/2023ss/bs/20230424> ls -l ../20230515/dev/chardev
+-rw-r--r-- 1 peter peter 0 Mai 15 15:56 ../20230515/dev/chardev
+cassini/home/peter/bo/2023ss/bs/20230424> cat ../20230515/dev/chardev
+cassini/home/peter/bo/2023ss/bs/20230424> cat ../20230424/dev/chardev
+I already told you 12 times Hello world!
+cassini/home/peter/bo/2023ss/bs/20230424>
diff --git a/20230515/dev/chardev b/20230515/dev/chardev
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/20230515/hello-01.c b/20230515/hello-01.c
new file mode 100644
index 0000000000000000000000000000000000000000..b19d80e9bd0bd7c5ed8f54b20c6a50d9166f03ac
--- /dev/null
+++ b/20230515/hello-01.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main (void)
+{
+  printf ("Hello, world!\n");
+  return 0;
+}
diff --git a/20230515/hello-01.s b/20230515/hello-01.s
new file mode 100644
index 0000000000000000000000000000000000000000..d28460b3f7c060c295e386c0d45fc075ee693bc3
--- /dev/null
+++ b/20230515/hello-01.s
@@ -0,0 +1,24 @@
+	.file	"hello-01.c"
+	.text
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.LC0:
+	.string	"Hello, world!"
+	.text
+	.globl	main
+	.type	main, @function
+main:
+.LFB11:
+	.cfi_startproc                            ; #include <stdio.h>
+	subq	$8, %rsp                          ; 
+	.cfi_def_cfa_offset 16                    ; int main (void)
+	leaq	.LC0(%rip), %rdi                  ; {
+	call	puts@PLT                          ;   printf ("Hello, world!\n");
+	movl	$0, %eax                          ;   return 0;
+	addq	$8, %rsp                          ; }
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE11:
+	.size	main, .-main
+	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/20230515/hello-02.c b/20230515/hello-02.c
new file mode 100644
index 0000000000000000000000000000000000000000..b767f77cd3a7328e5f45b60e674d32a647386509
--- /dev/null
+++ b/20230515/hello-02.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main (void)
+{
+  puts ("Hello, world!");
+  return 0;
+}
diff --git a/20230515/hello-02.s b/20230515/hello-02.s
new file mode 100644
index 0000000000000000000000000000000000000000..b8b73c97cd1a7c692229600928d167d6cd12c624
--- /dev/null
+++ b/20230515/hello-02.s
@@ -0,0 +1,24 @@
+	.file	"hello-02.c"
+	.text
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.LC0:
+	.string	"Hello, world!"
+	.text
+	.globl	main
+	.type	main, @function
+main:
+.LFB11:
+	.cfi_startproc                            ; #include <stdio.h>
+	subq	$8, %rsp                          ; 
+	.cfi_def_cfa_offset 16                    ; int main (void)
+	leaq	.LC0(%rip), %rdi                  ; {
+	call	puts@PLT                          ;   puts ("Hello, world!");
+	movl	$0, %eax                          ;   return 0;
+	addq	$8, %rsp                          ; }
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE11:
+	.size	main, .-main
+	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/20230515/hello-03.c b/20230515/hello-03.c
new file mode 100644
index 0000000000000000000000000000000000000000..0e56d5a33a3ac5f71ac2f06073beb86162ca8947
--- /dev/null
+++ b/20230515/hello-03.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int main (void)
+{
+  write (1, "Hello, world!\n", 14);
+  return 0;
+}
diff --git a/20230515/hello-03.s b/20230515/hello-03.s
new file mode 100644
index 0000000000000000000000000000000000000000..a51ecbf30868f33c7a32781117e1bac6feddb6be
--- /dev/null
+++ b/20230515/hello-03.s
@@ -0,0 +1,26 @@
+	.file	"hello-03.c"
+	.text
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.LC0:
+	.string	"Hello, world!\n"
+	.text
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.cfi_startproc
+	subq	$8, %rsp
+	.cfi_def_cfa_offset 16
+	movl	$14, %edx
+	leaq	.LC0(%rip), %rsi
+	movl	$1, %edi
+	call	write@PLT
+	movl	$0, %eax
+	addq	$8, %rsp
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/20230515/minor-numbers-01.txt b/20230515/minor-numbers-01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f2e359cad48ce3a67f98ec7481e627a75699d4d3
--- /dev/null
+++ b/20230515/minor-numbers-01.txt
@@ -0,0 +1,6 @@
+cassini/home/peter/bo/2023ss/bs/20230424> ls -l /dev/sda*
+brw-rw---- 1 root disk 8, 0 Apr 20 22:38 /dev/sda
+brw-rw---- 1 root disk 8, 1 Apr 20 22:38 /dev/sda1
+brw-rw---- 1 root disk 8, 2 Apr 20 22:38 /dev/sda2
+brw-rw---- 1 root disk 8, 3 Apr 20 22:38 /dev/sda3
+cassini/home/peter/bo/2023ss/bs/20230424>