Robotrontechnik-Forum

Registrieren || Einloggen || Hilfe/FAQ || Suche || Mitglieder || Home || Statistik || Kalender || Admins Willkommen Gast! RSS

Robotrontechnik-Forum » Technische Diskussionen » U8000 - Problem mit einem ASM Listing » Themenansicht

Autor Thread - Seiten: -1-
000
13.04.2008, 16:35 Uhr
Olli

Avatar von Olli

Hallo,

gleich vorneweg - es ist ein recht langer Text, ich hoffe jedoch jemand liest ihn trozdem....

Ich versuche gerade K5JB (eine userland TCP/IP Loesung) unter WEGA zu compilieren.

Den Samstag habe ich damit verbracht den Fehler zu suchen der im C-Compiler lcc steckt(e) variable Funktionen aufzurufen (CALLR) die den C-Datentyp void und nicht z.B. int zurueckliefern. Das habe ich dann heute morgen so gegen 1 Uhr gefixt gehabt. Nun stehe ich vor einem etwas schwierigerem Problem wo ich Eure Hilfe brauche, da dies sehr ASM-lastig ist.

Es gibt unter WEGA eine C-Funktion namens fcntl. Diese Funktion wird im Kernel bereitgestellt. Die Funktion im Kernel wird ueber einen sogenannten syscall aufgerufen. Die Funktion welche in der C-Funktionsibliothek "libc" zur Verfuegung steht, reicht die Argumente quasi ueber den syscall direkt an den Kernel durch, und dort wird dann die eigentliche fcntl Funktion ausgefuehrt.

Fcntl erwartet 3 Argumente. Als erstes Argument wird ein Dateizeiger uebergeben, dann wird das Kommando uebergeben welches die Aktion beschreibt die fcntl mit dem Dateizeiger durchfuehren soll. Das dritte Argument spezifiziert die Aktion naeher.

Ein kurzes Beispiel. Moechte ich ermitteln, ob eine geoeffnete Datei fuer "non blocking I/O" aufgerufen wurde, rufe ich z.B. folgendes auf file_flags = fcntl(fd, F_GETFL, 0) dann stehen in file_flags welche aktuell fuer diese Datei gueltig sind (wurde sie lesen, schreiben oder schreib/lesend geoffnet, wurde sie so geoeffnet, das ein schreiben nur am ende angehangen wird, oder wurde sie fuer non-blocking-I/O geoeffnet).

Ich habe hier als Beispiel einen kurzen C-Quellcode ohne Fehlerhandling (damit das ASM Listing kuerzer wird):


Quellcode:
#include <stdio.h>
#include <fcntl.h>

main() {
        char cul[90];
        int fd=0,fd2;

        strcpy(cul,"/tmp/test");
      
        fd = open(cul, O_EXCL | O_RDWR | O_NDELAY);
        fd2 = fcntl(fd, F_DUPFD,0 );
        printf("%d -> %d\n",fd,fd2);
}

Dieses Programm oeffnet dann die Datei /tmp/test und erzeugt mir dann mit fcntl() ein Duplikat des Dateizeigers. Compiliert und ausgefuehrt mit dem segmentierenden Systemcompiler scc sieht das dann so aus:


Quellcode:
#182 scc -o fcntl_test fcntl_test.c
#183 ./fcntl_test
3 -> 4
#184

Man sieht also, das der Dateizeiger mit der ID 3 dupliziert wurde, und ich nun mit fd2 einen Dateizeiger mit der ID 4 habe.

Mit scc funktioniert also alles wie es soll. Mit dem lcc (den ich fuer das TCP/IP Programm verwenden muss aufgrund der Sprachkomplexitaet) sieht es aber so aus:


Quellcode:
#187 lcc -o fcntl_test fcntl_test.c
#188 ./fcntl_test
3 -> -1
#189

Hier kommt also -1 zurueck, und -1 bedeutet das fcntl nicht erfolgreich ausgefuehrt werden konnte. Als Fehler selbst kommt

[EBADF] Fildes ist kein gueltiger offener Dateidescriptor.

zurueck.

Nun frage ich mich - warum klappt das mit scc, und warum mit lcc nicht. Lcc benutzt eine andere - eigene - libc als scc. Ich nam also an, vielleicht ist der Fehler in der C-Bibliothek selbst zu suchen. Wenn ich mir aber das Objekt welches den fcntl syscall an den Kernel durchschleift aus der scc libc herausloese, und es in die lcc libc einfuege komme ich zum gleichen Fehler.
Neme ich das fcntl-Objekt aus der libc des lcc und fuege dies in die libc des scc ein, bekomme ich mit scc den gleichen Fehler. Das verwundert mich:

- Compiler scc, fcntl-Objekt von scc: funktioniert
- Compiler scc, fcntl-Objekt von lcc: funktioniert nicht
- Compiler lcc, fcntl-Objekt von lcc: funktioniert nicht
- Compiler lcc, fcntl-Objekt von scc: funktioniert nicht

Ich haette etwas anderes erwartet....

Nun kann es also sowohl an der libc-Implementation der fcntl Funktion des lcc liegen, als auch an dem lcc Compiler selbst (erzeugt fehlerhaften ASM Code).

Ich habe hier mal den Sourcecode der libc-Implementation der fcntl Funktion des lcc:


Quellcode:
.
        .seg

        sp := r15
        SP := rr14

        .psec
        .code
_fcntl::
        {
        ldm     r0,|_stkseg+3|(sp),#4
        xor     r4,r4
        sc      #38                       // switch
        ld      r2,r4
        ret     nc
        jp      cerror
        }

Der hexdump des daraus entstandenen Objektes sieht so aus:


Quellcode:
0000000 e607 0000 0014 0000 0000 0010 002a 0000
0000010 0000 0000 0000 0000 0000 0000 0014 0000
0000020 0000 0001 0000 0000 5cf1 0003 0003 8944
0000030 7f26 a142 9e0f 5e08 8000 0000 0000 0000
0000040 001a 0000 0000 0000 0000 0000 0029 0028
0000050 0000 0000 2200 5f66 636e 746c 0000 0000
0000060 0000 2000 5f73 746b 7365 6700 0000 0000
0000070 2000 6365 7272 6f72 0000

Adresse 30-31 ist der Syscall auf #28.

Von der libc-Implementation der fcntl Funktion des scc habe ich leider keinen ASM source, kann hier also nur mit dem Hexdump dienen wo ich sehe das er unterschiedlich ist, ich das aber nicht zurueck in Mnemonik "geparsed" kriege im Kopf um den Unterschied zu erkennen:


Quellcode:
0000000 e607 0000 0014 0000 0000 0020 0038 0000
0000010 0000 0000 0000 0000 0000 0000 0014 0000
0000020 0000 0001 0000 0000 0100 0000 0000 0000
0000030 0000 0002 0000 0000 a170 a161 a152 8344
0000040 7f26 a142 9e0f 5e08 8000 0000 0000 0000
0000050 0000 0000 0000 0000 0000 0000 0039 0038
0000060 0000 0000 1e00 6663 6e74 6c5f 7000 0100
0000070 0000 1e01 6663 6e74 6c5f 6400 0000 0000
0000080 6200 5f66 636e 746c 0000 0000 0000 6000
0000090 6365 7272 6f72 0000
0000098

Dort ist der Syscall auf die gleiche Adresse bei 40/41 zu finden. Also wird schonmal der gleiche Syscall ausgefuehrt, nur vorher und nachher passiert bei der scc Implementation ein bischen was anderes....

Wenn ich mir nun das ASM Listing, welches der lcc aus meiner C-Datei erzeugt anschaue: (nur der Ausschnitt mit dem fcntl Aufruf):


Quellcode:
.
        .seg
        fp := r13
        FP := rr12
        sp := r15
        SP := rr14
[...]
        callr   _open
        inc     sp,#%6
        ld      FP(#~L1+%5a),r2
        xor     r2,r2
        push    @SP,r2
        xor     r2,r2
        push    @SP,r2
        push    @SP,_stkseg+~L1+%5a(fp)
        callr   _fcntl
        inc     sp,#%6

und mir jetzt den Code den der scc Compiler erzeugt anschaue:


Quellcode:
.
        .seg
        .psec data
        .data


        fp              := r15;
        sp              := rr14;
[...]
        callr   _open
        ld      |_stkseg+~L1+90|(fp),r2
        ld      r7,|_stkseg+~L1+90|(fp)
        sub     r6,r6
        sub     r5,r5
        callr   _fcntl
        ld      |_stkseg+~L1+92|(fp),r2

sieht man da schon Unterschiede - und hier hoerts nun auf. Ich weiss nicht wie ich mit dem ASM Code weiterverfahren soll, da mein ASM Wissen nun leider auch noch recht limitiert ist.

Eine moegliche Implementation von einem SYSIII der Funktion fcntl im Kernel ist hier: http://pofo.de/P8000/misc/fcntl.c
Wie gesagt, das muss nicht die Funktion sein, so wie sie im WEGA-Kernel implementiert ist. Sie wird aber sehr aenlich sein.

Kann jemand aus dem Hexdump der fcntl-Implementation des scc ein ASM-Listing "rueckwaerts" erzeugen?
Hat jemand eine Idee was mein lcc da falsch macht?
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 16:43 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
001
13.04.2008, 18:19 Uhr
Olli

Avatar von Olli

Es gibt ein WEGA-Kommando mit dem man das Objekt "dumpen" kann, und er die header Infos auswertet. Da kommt man dann an den reinen "Code" ohne Header und Symboltabelle am Ende - der Hexdump in der Ausgabe ist dann das eigentliche Programm. Das versteht man dann etwas besser als die beiden HEX-Ausgaben in meinem 1. Posting

Vielleicht kann mir das jemand fuer libc_sys/fcntl.o "zurueckuebersetzen"? nach dem systemcall scheinen ja beide gleich zu sein, nur vorher passiert was anderes....

SCC:


Quellcode:
#259 objdu libc_sys/fcntl.o
File libc_sys/fcntl.o
Image size:     20
Bss size:       0
Entry point:    0x0
Segment 0
Text size:      20
Data size:      0
Bss size:       0
Text+Data......

0000:     a170  a161  a152  8344  7f26  a142  9e0f  5e08
0010:     8000  0000

Segment 1
Text size:      0
Data size:      0
Bss size:       0
Text+Data......

LCC:


Quellcode:
#260 objdu libc_lcc/fcntl.o
File libc_lcc/fcntl.o
Image size:     20
Bss size:       0
Entry point:    0x0
Segment 0
Text size:      20
Data size:      0
Bss size:       0
Text+Data......

0000:     5cf1  0003  0003  8944  7f26  a142  9e0f  5e08
0010:     8000  0000


hier mal die LCC "uebersetzung":


Quellcode:
5cf1  0003  0003   =   ldm     r0,|_stkseg+3|(sp),#4
8944               =   xor     r4,r4
7f26               =   sc      #38
a142               =   ld      r2,r4
9e0f               =   ret     nc
5e08  8000  0000   =   cp      cerror

Kann das jemand fuer den SCC Teil?
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 18:31 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
002
13.04.2008, 18:36 Uhr
Tom Nachdenk



Gibt es bei WEGA keinen Disassembler? Oder Debugger der symbolische Mnemonics ausgibt? Das die 'Calling Conventions' der Compiler voneinander abweichen ist ja mehr oder weniger 'üblich'. Allerdings müsste das Beladen des Stacks vor dem Syscall ja im Endeffekt effektiv gleich sein.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
003
13.04.2008, 18:42 Uhr
Enrico
Default Group and Edit


Olli, und da behauptest Du C soll einfach sein?
Das sieht alles wie altägypthisch aus.
Willst Du dich jetzt doch ans Ethernet ranwagen?
--
MFG
Enrico
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
004
13.04.2008, 18:51 Uhr
Tom Nachdenk



kommt das hin?

a170 ldw 7,0
a161 ldw 6,1
la161 dw 5,2

evtl. hab ich bei den Registern Ziel und Quelle vertauscht.

Manuell disassemblieren geht halbwegs wenn man im Brennenstuhl die Matrix mit den Befehlscodierungen und die Übersicht zu den Befehlsformaten aus dem WIssensspeicher Mikrorechnerprogrammierung benutzt.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
005
13.04.2008, 18:53 Uhr
Tom Nachdenk



@Enrico:
Erstmal an TCP/IP (über PPP oder SLIP) und dann vielleicht Ethernet
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
006
13.04.2008, 19:01 Uhr
Olli

Avatar von Olli

der SCC Teil muesste wohl


Quellcode:
a170               =   ld      r0,r7
a161               =   ld      r1,r6
a152               =   ld      r2,r5
8344               =   ???     r4,r4
7f26               =   sc      #38
a142               =   ld      r2,r4
9e0f               =   ret     nc
5e08  8000  0000   =   cp      cerror

Ergeben, nur ??? ist mir nicht klar - 86 ist xor, nur was ist 83?

Enrico - wenn der generierte ASM Code funktionieren wuerde waere ja alles in Butter
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
007
13.04.2008, 19:02 Uhr
Olli

Avatar von Olli


Zitat:
Tom Nachdenk schrieb
@Enrico:
Erstmal an TCP/IP (über PPP oder SLIP) und dann vielleicht Ethernet

Genau - erstmal SLIP, dann wahlweise Ethernet und/oder TCP/IP im Kernel

In ferner Zukunft sehe ich also eine Ethernetkarte die mir der Enrico baut (logo, wer sonst? ), und einen schoenen multiuser TCP/IP Stack im Kernel und ner C-Bibliothek die BSD-kompatibel ist...
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 19:03 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
008
13.04.2008, 19:13 Uhr
Tom Nachdenk



83 ist sub

Ergebnis ist das selbe, nämlich ein Register das 0 ist.

Dieser Beitrag wurde am 13.04.2008 um 19:15 Uhr von Tom Nachdenk editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
009
13.04.2008, 19:24 Uhr
Olli

Avatar von Olli

Ok, er leert r4 um sicherzugehen, dass das Ergebniss des Systemcalls welches in r4 stehen soll, und dann nach r2 geladen wird, wirklich das Ergebniss des Systemcalls ist, und nicht irgendwelcher alter Mist der noch im Register stand.

Was ich nun aber nicht verstehe ist, er laed im fcntl.o r6 nach r1, r5 nach r2 und er leert r4 - soweit so gut. Aber wiso laedt er r5 und r6 ueberhaupt um? Wir erinnern uns - im generierten ASM Listing vom C-Compiler steht:


Quellcode:
.
        ld      r7,|_stkseg+~L1+90|(fp)
        sub     r6,r6
        sub     r5,r5
        callr   _fcntl

in r5 und r6 stehen also 0.
Welchen Sinn macht dann:


Quellcode:
.
   ld      r0,r7
   ld      r1,r6
   ld      r2,r5
   sub     r4,r4
   sc      #38

?

Edit: ich glaube ich weiss warum. in meinem code steht ja fcntl(fd,0,0) r6 ist dann wohl das 1. 0, und r5 das 2. 0 - und in meinem ASM-Listing von meinem Testprogramm macht er diese 0 eben indem er r5 mit r5 und r6 mit r6 subtrahiert....
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 19:42 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
010
13.04.2008, 19:47 Uhr
Enrico
Default Group and Edit



Zitat:
Olli schrieb
In ferner Zukunft sehe ich also eine Ethernetkarte die mir der Enrico baut (logo, wer sonst? ), und einen schoenen multiuser TCP/IP Stack im Kernel und ner C-Bibliothek die BSD-kompatibel ist...

Na, dann wäre es ja einfacher gleich das WizNet zu nehmen. Dann brauchst Du dich nicht drum zu kümmern
--
MFG
Enrico
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
011
13.04.2008, 20:00 Uhr
Olli

Avatar von Olli

So,

nun habe ich ein fcntl was funktioniert - aber sehr sehr gefrickelt - das will ich nicht so lassen
Ich habe mir jetzt ein fcntl.s gebastelt was in meiner libc ruht das so aussieht:


Quellcode:
.
        .seg

        sp := r15
        SP := rr14

        .psec
        .code
_fcntl::
        {
        ld      r0,r7
ld      r1,r6
ld      r2,r5
sub     r4,r4
        sc      #38                       // switch
        ld      r2,r4
        ret     nc
        jp      cerror
        }

mein Test C-Source wurde ja zu folgendem ASM Code verwandelt:


Quellcode:
.
        callr   _open
        inc     sp,#%6
        ld      FP(#~L1+%5a),r2
        xor     r2,r2
        push    @SP,r2
        xor     r2,r2
        push    @SP,r2
        push    @SP,_stkseg+~L1+%5a(fp)
        callr   _fcntl
        inc     sp,#%6

Den habe ich nun haendisch zu folgendem Ergebniss veraendert:


Quellcode:
.
        callr   _open
        inc     sp,#%6
        ld      FP(#~L1+%5a),r2
        ld      r7,r2
        sub     r5,r5
        sub     r6,r6
        xor     r2,r2
        push    @SP,r2
        xor     r2,r2
        push    @SP,r2
        push    @SP,_stkseg+~L1+%5a(fp)
        callr   _fcntl
        inc     sp,#%6

compilieren tut das ganze, und es laeuft auch:


Quellcode:
.
#324 !-3
lcc -o fcntl_test fcntl_test.s
#325 !-3
./fcntl_test
3 -> 4 error: 0

ABER - ich habe den asm code nun haendisch editiert - das ist natuerlich mist. Ich will es schon richtig "fixen". Ich nehme an, dass das speichern des Filepointers welcher von _open in r2 zurueckgeliefert wird, nicht dort abgelegt wird, wo das original fctnl den pointer abholt (r0,|_stkseg+3|(sp),#4)

Was man im generierten ASM Code erkennt:

r2 nach open wird in "FP(#~L1+%5a)" abgelegt, FP ist rr12
danach wird "_stkseg+~L1+%5a(fp)" nach @SP gepused fp ist r13, SP ist rr14

fcntl aus der libc liest nun den filepointer aus |_stkseg+3|(sp) 4 Worte nach r0. sp ist rr14

Passt das zusammen? Offensichtlich nicht...

Kann mir mal einer dieses FP(#~L1+%5a) erklaeren?
Was bedeuten die Pipes um _stkseg?
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 22:30 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
012
13.04.2008, 20:03 Uhr
Olli

Avatar von Olli


Zitat:
Enrico schrieb
Na, dann wäre es ja einfacher gleich das WizNet zu nehmen. Dann brauchst Du dich nicht drum zu kümmern

Ist das das ding was fuer den KC verwendet wurde? Mein Ziel ist es zummindest Systemseitig einen 100% kompatiblen BSD TCP/IP Stack zu haben der vor allem auch noch multiuserfaehig ist(!) also mit threading auskommt... das wird aber halt nicht so einfach, da dann der Kernel erstmal Interprozesskommunikation und Semaphoren koennen muss - und das kann er nicht - das ist ne riesige Baustelle - deswegen fange ich jetzt erstmal klein ran - und lerne nebenbei noch so die Interna des Compilers und etwas ASM
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
013
13.04.2008, 20:06 Uhr
Enrico
Default Group and Edit


Ja, genau das Dingens ist das.
Sowas in der Art dachte ich mir schon was.

Aber irgendwo hatte ich so einen Ethernet-Chip in DIP für MCs auch schon mal wo gesehen. Da darf man sich dann um die SW selber kümmern.
--
MFG
Enrico
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
014
13.04.2008, 20:44 Uhr
Olli

Avatar von Olli

So Kinders... ich habe den Fehler gefunden.

in fcntl.s fuer den lcc muss es nicht


Quellcode:
ldm     r0,|_stkseg+3|(sp),#4

sondern


Quellcode:
ldm     r0,|_stkseg+4|(sp),#4

heissen - rausgefunden habe ich es, indem ich mir die anderen Syscall Implementationen welche mit Dateizeigern arbeiten angeschaut, und die greiffen alle auf +4 und nicht +3 zu. Das duerfte dann damit der Fehler sein

vgl:
http://pofo.de/P8000/misc/sources/WEGA/cmd/lcc/lib/libc/u8k/sys/fcntl.s

http://pofo.de/P8000/misc/sources/WEGA/cmd/lcc/lib/libc/u8k/sys/ioctl.s
http://pofo.de/P8000/misc/sources/WEGA/cmd/lcc/lib/libc/u8k/sys/open.s

Nun klappts auch mit k5jb "erstmal" - zummindest das Starten - morgen muss ich mir mal ein Terminal aus dem Keller holen und dann das serielle Kabel fuer den PC fuer den 1. SLIP Versuch missbrauchen...


Quellcode:
#381 ./net
Internet Protocol Package, (C) 1988 by Phil Karn, KA9Q
      NET/ROM Support (C) 1989 by Dan Frank, W9NK

             This puppy was housebroken by
     Joe Buswell, K5JB, 44.78.0.2, Midwest City OK

        This version is K5JB.k31 with options:
        AX.25, Netrom, MBOX, KPC4, Mulport, VC, Heard, Unix

net> attach asy
Usage: attach asy 0 <ttyname> slip|ax25 <label> 0 <mtu> <speed>
net> attach asy 0 /dev/tty4 slip sl0 0 1500 9600
asy_init: tty name = /dev/tty4
net> param sl0
9600
net>

Nur - kann mir mal einer die Dinge aus #11 am Ende erklaeren nach denen ich fragte? Will ja lernen was das ueberhaupt ist da...
--
P8000 adventures: http://pofo.de/blog/?/categories/1-P8000

Dieser Beitrag wurde am 13.04.2008 um 21:21 Uhr von Olli editiert.
Seitenanfang Seitenende
Profil || Private Nachricht || Suche Zitatantwort || Editieren || Löschen
Seiten: -1-     [ Technische Diskussionen ]  



Robotrontechnik-Forum

powered by ThWboard 3 Beta 2.84-php5
© by Paul Baecher & Felix Gonschorek