# Unterprogramme in Assembler



## Kirby.exe (14. Jan 2020)

@mihe7 Es ist wieder so weit....It`s Assembler time xD Könnte mir jemand erläutern wie Unterprogramme in Assembler funktionieren ?

In Java sind Unterprogramme z.B. Methoden:


```
public int getAnzahlCookies(int newCookie){
    return this.cookie + newCookie;
}
```

- Meine Fragen wäre z.B. wie übergebe ich Werte an das Unterprogramm?
- Ich weiß noch dass man irgendwie eine Rücksprung Adresse retten muss, jedoch wie und was genau?

Der Befehlsatz ist im Anhang


----------



## mihe7 (14. Jan 2020)

Kirby_Sike hat gesagt.:


> Meine Fragen wäre z.B. wie übergebe ich Werte an das Unterprogramm?


Allgemein kann man das nicht sagen, da Du in Assembler alle Freiheiten hast. Du könntest z. B. Register, einen Stack oder einen fixen Speicherbereich verwenden. Das gilt natürlich auch für Rückgabewerte. 



Kirby_Sike hat gesagt.:


> Ich weiß noch dass man irgendwie eine Rücksprung Adresse retten muss, jedoch wie und was genau?


Manual, ab Seite 8.


----------



## Kirby.exe (14. Jan 2020)

Thank uuuu


----------



## mihe7 (14. Jan 2020)

Noch ein Beispiel: unter DOS gibt's den berühmten Interrupt 21h für bestimmte Systemaufrufe. Ein Interrupt funktioniert zwar ein wenig anders aber das ändert am Prinzip der Parameter ja nichts. Das AH-Register wird mit der auszuführenden Funktion belegt (1. Parameter). Je nach Funktion können dann Parameter mit anderen Registern übergeben werden.


```
MOV dl, 65
MOV ah, 2 ; Ausgabe des in dl übergebenen Zeichens auf dem Bildschirm, also ein A
INT 21h
MOV ah, 0 ; Ende
INT 21h
```

Wenn Du die Übersetzung als .com-Datei speicherst und die unter DOS ausführst, erhältst Du ein A am Bildschirm ausgegeben. Für komplexere Dinge werden Speicheradressen in Registern übergeben. Der eigentliche Parameter befindet sich dann im Hauptspeicher. So gibt es die Funktion 9 (AH=9), bei der die Adresse eines Strings (also ein Zeiger auf den Beginn des Strings) in den Registern DS:DX erwartet wird.

Das gleiche Prinzip kannst Du natürlich für Unterprogramme verwenden. Bei mehreren Parametern bietet sich aber der Stack an, der ja auch nichts anderes ist als ein Bereich im Speicher.


----------



## Kirby.exe (14. Jan 2020)

mihe7 hat gesagt.:


> Noch ein Beispiel: unter DOS gibt's den berühmten Interrupt 21h für bestimmte Systemaufrufe. Ein Interrupt funktioniert zwar ein wenig anders aber das ändert am Prinzip der Parameter ja nichts. Das AH-Register wird mit der auszuführenden Funktion belegt (1. Parameter). Je nach Funktion können dann Parameter mit anderen Registern übergeben werden.
> 
> 
> ```
> ...


Naja ich darf wie wunderschöne Ackermann Funktion moderieren  Ich fuchse mich da schon irgendwie rein  Danke für deine Hilfe


----------



## mihe7 (14. Jan 2020)

Kirby_Sike hat gesagt.:


> ich darf wie wunderschöne Ackermann Funktion moderieren


Pass bloß auf, dass Du als Moderator neutral bleibst.


----------



## Xyz1 (14. Jan 2020)

Kirby_Sike hat gesagt.:


> It`s Assembler time xD


Ok, sagen wir Du möchtest x-y (Subtraktion) in Assembler berechnen

File: TutorialJNI.java

```
public class TutorialJNI {
	static {
		System.loadLibrary("tutorial");
	}
	private native int calculate(int x, int y);
	public static void main(String[] args) {
		System.out.println(new TutorialJNI().calculate(4, 5));
	}
}
```


Compile: javac -h . TutorialJNI.java
File: TutorialJNI.h (maschinell erstellt)

```
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TutorialJNI */

#ifndef _Included_TutorialJNI
#define _Included_TutorialJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TutorialJNI
 * Method:    calculate
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_TutorialJNI_calculate
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
```


File: TutorialJNI.c (Die Subtraktion in asm...)

```
#include <jni.h>
#include "TutorialJNI.h"
#include <stdint.h>

JNIEXPORT jint JNICALL Java_TutorialJNI_calculate(JNIEnv *env, jobject thisObj, jint x, jint y)
{
    uint32_t src1 = x;
    uint32_t src2 = y;
    uint32_t dst = 42;
    asm ("movl $1, %0\n\t"
    "subl $2, %0"
    : "=r" (dst) 
    : "r" (src1, src2));
    return dst;
}
```


Compile: x86_64-w64-mingw32-gcc -I"C:\Program Files\Java\jdk-12.0.1\include" -I"C:\Program Files\Java\jdk-12.0.1\include\win32" -shared -o tutorial.dll TutorialJNI.c
File: tutorial.dll

Run: java TutorialJNI
Result: ...

Das war auch schon alles


----------



## Kirby.exe (14. Jan 2020)

mihe7 hat gesagt.:


> Pass bloß auf, dass Du als Moderator neutral bleibst.


*modellieren xD Moderator werde ich vielleicht im nächsten Leben


----------



## Xyz1 (14. Jan 2020)

Kirby_Sike hat gesagt.:


> Ackermann Funktion


Das sollte jetzt eigentlich ziemlich leicht sein.


----------



## Kirby.exe (14. Jan 2020)

Tobias-nrw hat gesagt.:


> Das sollte jetzt eigentlich ziemlich leicht sein.


Wenn ich den Kram super könnte, dann höchstwahrscheinlich ja xD


----------



## Xyz1 (14. Jan 2020)

Ach ICH kann den Kram auch nicht super... Aber mir fällt gerade auf dass mit Funktionsprototypen (also Funktionsaufrufen) in Assembler nicht zu spaßen ist... Das ist eventuell auch nochmal eine Nuss.


----------



## Kirby.exe (14. Jan 2020)

Jap ich kämpfe gerade mit dem Stack....Ich glaube er mag mich einfach nicht xD Also ich bin mehr oder weniger fertig, muss halt noch irgendwie alle geretteten werde wieder vom Stack entnehmen


----------



## Xyz1 (14. Jan 2020)

Oh Sorry ich habe jetzt in die PDF geschaut.... Die ganze Code Wurst oben brauchst Du nicht... das macht pHILOs bereits...

Weiterhin gutes Gelingen.


----------



## Kirby.exe (14. Jan 2020)

Dankeschön  Wie ich @mihe7 schonmal erzählt habe, pHILO`s funktioniert mit Schwarzer Magie xD


----------



## Kirby.exe (14. Jan 2020)

Habe es geschafft


----------



## Kirby.exe (14. Jan 2020)

Also vielleicht hat mir die Ackermann Funktion einfach das Hirn frittiert...aber jetzt mal eine blöde Frage, könnte mir jemand in Worten sagen wie man überprüft ob zwei Zahlen Vielfache voneinander sind? 

Beispielsweise die Zahlen 2 und 4


----------



## Kirby.exe (14. Jan 2020)

Nevermind habs gelöst


----------



## Xyz1 (15. Jan 2020)

Modulo


----------



## Kirby.exe (15. Jan 2020)

Tobias-nrw hat gesagt.:


> Modulo


Nach 15 min hat mein totes Hirn auch mal klick gemacht


----------



## Xyz1 (15. Jan 2020)

Kirby_Sike hat gesagt.:


> Nach 15 min hat mein totes Hirn auch mal klick gemacht



Ein Zombie


----------



## mihe7 (15. Jan 2020)

Tobias-nrw hat gesagt.:


> Ein Zombie


Assemblerprogrammierer = Untoter - anders ist das nicht zu erklären


----------



## Xyz1 (15. Jan 2020)

Also die Ackermann-Funktion wäre in C-Inline- Assembler nicht schwer... es gibt aber praktisch gar keine Vorteile gegenüber einer normalen C-Funktion.  Oder?


----------



## mihe7 (15. Jan 2020)

Praktisch kannst Du die Ackermann-Funktion ohne nennenswerte Nachteile auch mit Hand ausrechnen


----------



## Xyz1 (15. Jan 2020)

Also das wär mein Verusch

```
#include <jni.h>
#include "TutorialJNI.h"
#include <stdint.h>

jint add1(jint x)
{
    asm("movl %1, %0\n\t"
        "addl $1, %0"
        : "=r"(x)
        : "r"(x));
    return x;
}

jint sub1(jint x)
{
    asm("movl %1, %0\n\t"
        "subl $1, %0"
        : "=r"(x)
        : "r"(x));
    return x;
}

JNIEXPORT jint JNICALL Java_TutorialJNI_calculate(JNIEnv *env, jobject thisObj, jint x, jint y)
{
    if (x == 0)
    {
        return add1(y);
    }
    if (y == 0)
    {
        return Java_TutorialJNI_calculate(env, thisObj, sub1(x), 1);
    }
    return Java_TutorialJNI_calculate(env, thisObj, 
    sub1(x), Java_TutorialJNI_calculate(env, thisObj, x, sub1(y)));
}
```


Sieht furchtbar aus ich weiß... Aber gibt das richtig aus.

Und hier hat jemand das für ziemlich viele Assemblersprachen bereits gemacht:
https://rosettacode.org/wiki/Ackermann_function 

@mihe7 für Ackermann(3, 8) kommt zum Bleistift 2045 raus - so weit kann ich gar nicht rechnen.


----------



## Kirby.exe (15. Jan 2020)

mihe7 hat gesagt.:


> Assemblerprogrammierer = Untoter - anders ist das nicht zu erklären


Gebe ich dir absolut recht xD Assembler bewirkt massive Kopfschmerzen


----------



## Kirby.exe (15. Jan 2020)

mihe7 hat gesagt.:


> Praktisch kannst Du die Ackermann-Funktion ohne nennenswerte Nachteile auch mit Hand ausrechnen


Habe ich getan  Ist im Anhang für Ackermann(2,3) 

Meine Ackermann Lösung in pHILO`s ist so:



Spoiler: Ackermann != schöne Funktion



#Einlesen von n
addi zero t1 1
sysmove exc t1
syscall

#Einlesen von m
addi zero t2 2
sysmove exc t2
syscall

#schiebe die Zahlen wieder in Register
sysmove a0 I[0] # a0 = n
sysmove a1 I[1] # a1 = m

#Retten der Rücksprung Adresse 
ldpc ra
addi ra ra 3
jmp ackermann


#Ausgabe des Ergebnis
sysmove O[0] v0
addi zero t6 6
sysmove exc t6
syscall
jmp ende

#Reguläre Beenden des Programms
ende:
sysmove exc zero
syscall


########################################################################################################
ackermann:

#Retten der Register auf den Stack
addi SP SP -12
sto SP ra 12
sto SP a0 8
sto SP a1 4

beq zero a0 first # falls n = 0
bgt a0 zero secondTest # n > 0
jmp third # else

secondTest:
beq zero a1 second # falls m = 0
jmp third # else


first:
ldd SP a1 4
addi a1 v0 1
ldd SP a1 4 # a1 vom Stack holen
ldd SP a0 8 # a0 vom Stack holen
ldd SP ra 12 # ra vom Stack holen
addi SP SP 12 #Stackpointer zurückschieben
stpc ra #Rücksprung 

second:
addi a0 a0 -1
addi zero a1 1
ldpc ra
addi ra ra 3 #Rücksprung Adresse retten
jmp ackermann
ldd SP a1 4 # a1 vom Stack holen
ldd SP a0 8 # a0 vom Stack holen
ldd SP ra 12 # ra vom Stack holen
addi SP SP 12 #Stackpointer zurückschieben
stpc ra #Rücksprung

third:
addi a1 a1 -1
ldpc ra 
addi ra ra 3 #Rücksprung Adresse retten
jmp ackermann
addi a0 a0 -1
addi v0 a1 0 #v1 in a1 kopieren
ldpc ra 
addi ra ra 3 #Rücksprung Adresse retten
jmp ackermann
ldd SP a1 4 # a1 vom Stack holen
ldd SP a0 8 # a0 vom Stack holen
ldd SP ra 12 # ra vom Stack holen
addi SP SP 12 #Stackpointer zurückschieben
stpc ra #Rücksprung


----------



## mihe7 (15. Jan 2020)

Tobias-nrw hat gesagt.:


> @mihe7 für Ackermann(3, 8) kommt zum Bleistift 2045 raus - so weit kann ich gar nicht rechnen.


Ok, aber wer berechnet die Funktion in der Praxis schon?


----------

