Skip to content
Snippets Groups Projects
Commit 151f6c80 authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Notizen und Beispiele 1.6.2023

parent 017efb67
No related branches found
No related tags found
No related merge requests found
Showing
with 461 additions and 1 deletion
...@@ -13,6 +13,7 @@ heute: ...@@ -13,6 +13,7 @@ heute:
der Treibhausgasemissionen des Pendelverkehrs für die Treibhausgasbilanz der der Treibhausgasemissionen des Pendelverkehrs für die Treibhausgasbilanz der
Hochschule Bochum. Zum anderen soll die Bekanntheit und Nutzung bestehender Hochschule Bochum. Zum anderen soll die Bekanntheit und Nutzung bestehender
Mobilitätsangebote abgefragt werden, die die BO klimafreundlicher gestalten. Mobilitätsangebote abgefragt werden, die die BO klimafreundlicher gestalten.
--> https://befragung.hs-bochum.de/evasys/online.php?p=LU2AL
RSA, 25.05.2023, 16:20:49 RSA, 25.05.2023, 16:20:49
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
...@@ -74,5 +75,24 @@ als in einer Schleife fortwährend zu multiplizieren? ...@@ -74,5 +75,24 @@ als in einer Schleife fortwährend zu multiplizieren?
Aufgabe: Aufgabe:
(a) Gegeben zwei Zahlen b und e (vom Typ int). (a) Gegeben zwei Zahlen b und e (vom Typ int).
Berechnen Sie b^3 mittels binärer Exponentiation. Berechnen Sie b^e mittels binärer Exponentiation.
(b) Dasselbe modulo einer dritten Zahl n (vom Typ int). (b) Dasselbe modulo einer dritten Zahl n (vom Typ int).
Lösung: siehe binexp-*.c
Addition langer Zahlen, 01.06.2023, 17:37:20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Siehe: longadd-*.c, longadd-*.s, sum-*.s
Das Addieren mit Übertrag ("carry") ist in Assembler-Sprache einfacher(!)
als in C.
Addieren mit Übertrag in C mit der GNU Compiler Collection (GCC):
https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
Neue Aufgabe: Addieren beliebig langer Zahlen. Siehe: longadd-10.c
Hinweis für die Initialisierung langer Zahlen:
Um einen String mit einer Dezimalzahl in eine lange Zahl umzuwandeln,
braucht man bereits funktionierende Langzahlarithmetik.
Bei Hexadezimalzahlen kann man jeweils eine Hex-Ziffer in 4 Bit umwandeln.
#include <stdio.h>
#include <stdint.h>
void print_binary (uint32_t a)
{
uint32_t mask = 0x80000000; /* binär: Eine 1, 31 Nullen */
if (a & mask)
printf ("1");
else
printf ("0");
printf ("\n");
}
int main (void)
{
print_binary (42); /* binär: 101010 */
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_binary (uint32_t a)
{
uint32_t mask = 0x80000000; /* binär: Eine 1, 31 Nullen */
while (mask)
{
if (a & mask)
printf ("1");
else
printf ("0");
mask <<= 1; /* falsche Richtung */
}
printf ("\n");
}
int main (void)
{
print_binary (42); /* binär: 101010 */
return 0;
}
#include <stdio.h>
#include <stdint.h>
void print_binary (uint32_t a)
{
uint32_t mask = 0x80000000; /* binär: Eine 1, 31 Nullen */
while (mask)
{
if (a & mask)
printf ("1");
else
printf ("0");
mask >>= 1;
}
printf ("\n");
}
int main (void)
{
print_binary (42); /* binär: 101010 */
return 0;
}
#include <stdio.h>
#include <inttypes.h>
int bin_exp(int b, int e){
int ret = 1;
uint32_t i = 0x80000000;
while (!(i & e)) i >>= 1;
while (i > 0) {
ret = ret * ret;
printf("Q = %d\n", ret);
if(e & i){
ret = ret * b;
}
printf("M = %d\n", ret);
i >>= 1;
}
return ret;
}
int main (void){
int b = 2;
int e = 18;
printf("%d\n", bin_exp(b, e));
return 0;
}
#include <stdio.h>
#include <stdint.h>
int bin_exp (int b, int e)
{
int res = 1;
int pot = b;
uint8_t mask = 1;
while (mask <= e)
{
if (e & mask)
res *= pot;
pot *= pot;
mask <<= 1;
}
return res;
}
int main (void)
{
int b = 2;
int e = 18;
printf ("%d hoch %d = %d\n", b, e, bin_exp (b, e));
return 0;
}
#include <stdio.h>
#include <inttypes.h>
int bin_exp(int b, int e, int n){
int ret = 1;
uint32_t i = 0x80000000;
while (!(i & e)) i >>= 1;
while (i > 0) {
ret = (ret * ret) % n;
printf("Q = %d\n", ret);
if(e & i){
ret = (ret * b) % n;
}
printf("M = %d\n", ret);
i >>= 1;
}
return ret;
}
int main (void){
int b = 2;
int e = 18;
int n = 42;
printf("%d\n", bin_exp(b, e, n));
return 0;
}
#include <stdint.h>
uint64_t sum (uint32_t a, uint32_t b)
{
return a + b;
}
.file "longadd-01.c"
.text
.globl sum
.type sum, @function
sum:
.LFB0:
.cfi_startproc
leal (%rdi,%rsi), %eax
ret
.cfi_endproc
.LFE0:
.size sum, .-sum
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
#include <stdint.h>
uint64_t sum (uint32_t a, uint32_t b)
{
return (uint64_t) a + (uint64_t) b;
}
.file "longadd-02.c"
.text
.globl sum
.type sum, @function
sum:
.LFB0:
.cfi_startproc
movl %edi, %edi
movl %esi, %eax
addq %rdi, %rax
ret
.cfi_endproc
.LFE0:
.size sum, .-sum
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
.file "longadd-02.c"
.text
.globl sum
.type sum, @function
sum:
.LFB0:
.cfi_startproc
pushl %ebx ; (sichere das ebx-Register auf den Stack)
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
movl 8(%esp), %eax ; lade den Parameter a ins eax-Register (l = 32 Bit)
movl $0, %edx ; lade eine 0 ins edx-Register (32 Bit)
movl 12(%esp), %ecx ; lade den Parameter b ins ecx-Register (32 Bit)
movl $0, %ebx ; lade eine 0 ins ebx-Register (32 Bit)
addl %ecx, %eax ; addiere: eax += ecx. Merke den Übertrag im Carry-Bit.
adcl %ebx, %edx ; addiere: edx += ebx + Carry-Bit ("add with carry")
popl %ebx ; (hole den auf dem Stack gesicherten Wert zurück ins ebx-Register)
.cfi_restore 3
.cfi_def_cfa_offset 4
ret ; Rücksprung aus der Funktion. Der Rückgabewert (64 Bit)
.cfi_endproc ; liegt in den Registern rax/rdx (untere/obere 32 Bit)
.LFE0:
.size sum, .-sum
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
#include <stdio.h>
#include <stdint.h>
uint64_t sum (uint32_t a, uint32_t b)
{
return (uint64_t) a + (uint64_t) b;
}
int main (void)
{
uint32_t a = 0x80000007;
uint32_t b = 0x80000014;
uint64_t c = sum (a, b);
printf ("0x%08x + 0x%08x = 0x%016lx\n", a, b, c);
return 0;
}
#include <stdio.h>
#include <stdint.h>
typedef uint32_t uint128_t[4];
extern void sum (uint128_t a, uint128_t b, uint128_t result);
void print128 (uint128_t a)
{
printf ("0x%08x 0x%08x 0x%08x 0x%08x", a[0], a[1], a[2], a[3]);
}
int main (void)
{
uint128_t a = { 0, 0x80000007, 0x12345678, 0x87654321 };
uint128_t b = { 0, 0x80000014, 0x98765432, 0x87654321 };
/* -------------1-----------------------1------------ */
/* 1, 0x0000001b, 0xaaaaaaab, 0x0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= ");
print128 (c);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
typedef uint32_t uint128_t[4];
void sum (uint128_t a, uint128_t b, uint128_t result)
{
result[3] = a[3] + b[3]; /* Fehler: Übertrag ("carry") nicht berücksichtigt! */
result[2] = a[2] + b[2];
result[1] = a[1] + b[1];
result[0] = a[0] + b[0];
}
void print128 (uint128_t a)
{
printf ("0x%08x 0x%08x 0x%08x 0x%08x", a[0], a[1], a[2], a[3]);
}
int main (void)
{
uint128_t a = { 0, 0x80000007, 0x12345678, 0x87654321 };
uint128_t b = { 0, 0x80000014, 0x98765432, 0x87654321 };
/* -------------1-----------------------1------------ */
/* 1, 0x0000001b, 0xaaaaaaab, 0x0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= ");
print128 (c);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
typedef uint32_t uint128_t[4];
extern void sum (uint128_t a, uint128_t b, uint128_t result);
void print128 (uint128_t a)
{
printf ("0x%08x 0x%08x 0x%08x 0x%08x", a[0], a[1], a[2], a[3]);
}
int main (void)
{
uint128_t a = { 0, 0x80000007, 0x12345678, 0x87654321 };
uint128_t b = { 0, 0x80000014, 0x98765432, 0x87654321 };
/* -------------1-----------------------1------------ */
/* 1, 0x0000001b, 0xaaaaaaab, 0x0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= ");
print128 (c);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
typedef uint64_t uint128_t[2];
void sum (uint128_t a, uint128_t b, uint128_t result)
{
result[1] = a[1] + b[1]; /* Fehler: Übertrag fehlt! */
result[0] = a[0] + b[0];
}
void print128 (uint128_t a)
{
printf ("0x%08lx 0x%08lx 0x%08lx 0x%08lx", a[0] >> 32, a[0] & 0xffffffff, a[1] >> 32, a[1] & 0xffffffff);
}
int main (void)
{
uint128_t a = { 0x0000000080000007, 0x1234567887654321 };
uint128_t b = { 0x0000000080000014, 0x9876543287654321 };
/* ----------------------1-------------------1-------- */
/* 0x000000010000001b, 0xaaaaaaab0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= "); /* Vorsicht, Falle: Die Ausgabe ist korrekt, weil in unserem Beispiel */
print128 (c); /* der Übertrag nur jeweils innerhalb einer 64-Bit-"Ziffer" stattfindet, */
printf ("\n"); /* aber nicht von der rechten "Ziffer" zur linken. */
return 0;
}
#include <stdio.h>
#include <stdint.h>
typedef uint64_t uint128_t[2];
extern void sum (uint128_t a, uint128_t b, uint128_t result);
void print128 (uint128_t a)
{
printf ("0x%08lx 0x%08lx 0x%08lx 0x%08lx", a[0] >> 32, a[0] & 0xffffffff, a[1] >> 32, a[1] & 0xffffffff);
}
int main (void)
{
uint128_t a = { 0x0000000080000007, 0x1234567887654321 };
uint128_t b = { 0x0000000080000014, 0x9876543287654321 };
/* ----------------------1-------------------1-------- */
/* 0x000000010000001b, 0xaaaaaaab0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= "); /* Der Fehler von vorhin ist jetzt behoben. Das sehen wir aber nicht, */
print128 (c); /* weil das Beispiel auf das Auftreten dieses Fehlers nicht testet. */
printf ("\n");
return 0;
}
include <stdio.h>
#include <stdint.h>
typedef uint64_t uint128_t[2];
extern void sum (uint128_t a, uint128_t b, uint128_t result);
void print128 (uint128_t a)
{
printf ("0x%08lx 0x%08lx 0x%08lx 0x%08lx", a[0] >> 32, a[0] & 0xffffffff, a[1] >> 32, a[1] & 0xffffffff);
}
int main (void)
{
uint128_t a = { 0x0000000080000007, 0x1234567887654321 };
uint128_t b = { 0x0000000080000014, 0xf876543287654321 };
/* ----------------------1-------1-----------1-------- */
/* 0x000000010000001c, 0x0aaaaaab0eca8642 */
uint128_t c;
sum (a, b, c);
printf (" ");
print128 (a);
printf ("\n+ ");
print128 (b);
printf ("\n= "); /* Jetzt ist die Ausgabe korrekt, weil die Funktion korrekt rechnet. */
print128 (c);
printf ("\n");
return 0;
}
#include <stdio.h>
#include <stdint.h>
#define N 42
/* 42 Zahlen à 64 Bit = 2688-Bit-Zahlen */
typedef uint64_t uintN_t[N];
extern void sum (uintN_t a, uintN_t b, uintN_t result); /* Übungsaufgabe */
/* Hinweis: Die bisherigen Beispiele verwendeten Big-Endian. Litte-Endian ist besser. */
void printN (uintN_t a)
{
/* Übungsaufgabe */
}
int main (void)
{
uintN_t a; /* Übungsaufgabe: Funktion(en) schreiben, um die Zahlen irgendwie */
uintN_t b; /* sinnvoll zu initialisieren, z.B. durch String mit Hex-Ziffern */
uintN_t c;
sum (a, b, c);
printf (" ");
printN (a);
printf ("\n+ ");
printN (b);
printf ("\n= ");
printN (c);
printf ("\n");
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment