Sie sind nicht angemeldet.

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

1

Dienstag, 27. Oktober 2015, 11:06

Maschinencode in Turbo Pascal

Hallo zusammen,

folgendes Basic-Listing, welches auf Maschinencode zurückgreift, würde ich gerne zu Turbo Pascal übertragen:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
10 MEMORY &HCB00-10
20 DIM tval%(25),cps%(25)
30 FOR i=0 TO 24
40 READ tval%(i),cps%(i)
50 NEXT
60 DATA 3324,131,3132,139,2961,147,2789,156,2636,165,2485,175,2350,185,2227,196
70 DATA 2098,208,1994,220,1863,233,1770,247,1655,262,1564,277,1473,294,1391,311
80 DATA 1311,330,1258,349,1167,370,1101,392,1039,415,979,440,924,466,877,493,819,524
90 GOSUB 410
100 RESTORE 170
110 PRINT: PRINT "Die zwei Oktaven....."
120 FOR scale=0 TO 14
130 READ note,duration
140 t%=tval%(note): c%=cps%(note)/8 * duration
150 CALL psound(t%,c%)
160 NEXT
170 DATA 0,4,2,1,4,1,5,1,7,1,9,1,11,1,12,4,14,1,16,1,17,1,19,1,21,1,23,1,24,4
180 FOR pause=0 TO 500: NEXT
190 PRINT: PRINT "Melodie:": PRINT
200 PRINT "Rule Britannia!": PRINT
210 FOR repaat=0 TO 1
220 tune$="O2E8E3F3F6E3F4E1D3O1C3B9B3O2G5F5E1D1E1F1G3F3E6D6O1C9"
230 GOSUB 260
240 NEXT
250 END
260 p=0:WHILE p<LEN(tune$)
270 n$=MID$(tune$,p+1,1)
280 IF n$="R" THEN p=p+1: rest=VAL(MID$(tune$,p+1,1)): FOR r=0 TO rest*25:NEXT:GOTO 380
290 IF n$="O" THEN p=p+1: oct=VAL(MID$(tune$,p+1,1)): GOTO 380
300 note=INSTR(1,"D_EF_G_A_BC",n$)-1
310 IF oct=2 THEN note=note+12
320 IF MID$(tune$,p+2,1)="#" THEN note=note+1: p=p+1
330 IF MID$(tune$,p+2,1)="b" THEN note=note-1: p=p+1
340 p=p+1
350 duration=VAL(MID$(tune$,p+1,1))
360 t%=tval%(note) : c%=cps%(note)/10 * duration
370 CALL psound(t%,c%)
380 p=p+1
390 WEND
400 RETURN
410 RESTORE 540
420 address=&HCB00
430 FOR i=1 TO 12
440 sum=0: READ mcode$,check$
450 FOR j=1 TO 21 STEP 2
460 byte=VAL("&H"+MID$(mcode$,j,2))
470 POKE address,byte
480 sum=sum+byte: address=address+1
490 NEXT
500 REM IF sum<>VAL("&H"+check$) THEN PRINT "Fehler in M-Code data":STOP
510 NEXT
520 psound=&HCB00
530 RETURN
540 DATA e5d5c5dde54e2346eb5e23,664
550 DATA 566960cd1bcb3e0cd3f8dd,5c4
560 DATA e1c1d1e1c9f37dcb3dcb3d,79d
570 DATA 2fe6034f0600dd2130cbdd,443
580 DATA 093e0b000000040c0d20fd,18c
590 DATA 0e3f0520f83cfe0d20023d,310
600 DATA 3dd3f8444ffe0b20097ab3,4fa
610 DATA 2809794d1bdde94d0cdde9,4f7
620 DATA fbc90d0a43423432206d6f,3c2
630 DATA 64756c610943423533206c,326
640 DATA 7032094342353720657869,302
650 DATA 74091ac974091a00000000,1f7


Die DATA-Zeilen werde ich vermutlich in ARRAYS übertragen müssen, oder? Wie sieht es mit Pascal-Entsprechungen für die Basic-Befehle MEMORY, CALL, PEAK und POKE aus?

Vielen Dank im voraus!

2

Dienstag, 27. Oktober 2015, 11:32

Ich verweiss da mal auf folgenden Thread: Ports mit Turbo Pascal abfragen
Besonders interessant für Dich dürfte das dort angegebene PDF zu Turbo Pascal sein, dass vermutlich alle Fragen beantwortet:
http://bitsavers.trailing-edge.com/pdf/b…Manual_1986.pdf

3

Dienstag, 27. Oktober 2015, 11:38

Wie sieht es mit Pascal-Entsprechungen für die Basic-Befehle MEMORY, CALL, PEAK und POKE aus?

Kenn' jetzt Basic nicht so doll, MEMORY/PEEK/POKE dürften sich aber mittels des Mem-Arrays umsetzen lassen, für CALL gibt's keine Entsprechung, weil unnötig (eine Funktion/Procedur wird dort einfach mittels ihres Namens aufgerufen).

ChaosRom

Fortgeschrittener

  • »ChaosRom« ist männlich

Beiträge: 402

Wohnort: Ditzingen

Lieblingscomputer: Ich rück keinen mehr raus!

  • Nachricht senden

4

Dienstag, 27. Oktober 2015, 12:10

Für die Kombination aus "note" und "duration" würde ich Dir den Recotd Type ans Herz legen.
Das PDF kennst Du ja sicher schon aus Deinem Thread über die Ports. 8-)
Da sind die Records auf Seite 79 erklärt.
In-line Machine Code wird ab 211 beschrieben.
Das Genie beherrscht das Chaos

ChaosRom

Fortgeschrittener

  • »ChaosRom« ist männlich

Beiträge: 402

Wohnort: Ditzingen

Lieblingscomputer: Ich rück keinen mehr raus!

  • Nachricht senden

5

Dienstag, 27. Oktober 2015, 12:15

Btw auf Seite 185 steht, wie am Sound erzeugt. Mit Sound(integer f_Hz), Delay(integer t_ms) und NoSound() um's wieder auszuschalten.
Das Genie beherrscht das Chaos

Beiträge: 688

Wohnort: Dresden (nahebei)

Lieblingscomputer: Acorn RISC OS + +4

  • Nachricht senden

6

Dienstag, 27. Oktober 2015, 12:18

Die DATA Zeilen enthalten ja Unterschiedliches.
Die ab der Zeile 540 sind das Maschinenprogramm für die Soundausgabe. Diese kannst Du direkt mit dem Kommando "INLINE" eintippen, da müssen dann aber natürlich die Checksummen (jeweils am Ende der Zeile weggelassen werden).
siehe (Seite 274): http://fjkraan.home.xs4all.nl/comp/tp30/tp30_22.html

Die DATA am Anfang sind die Tonhöhenwerte und noch was, was evtl. eine Standardlänge ist. Die würde ich als CONST Konstanten ablegen und zwar schön getrennt voneinander. CONST einfach deshalb, weil man die direkt mit Werten vorbelegen kann, was bei Variablen im Pascal zickig sein kann und je nach Compiler unterschiedlich ist.
siehe (ganz unten): http://www2.informatik.uni-halle.de/lehr…e/pas_arry.html

Die tune$ Variable in der Mitte ist die Melodie in Noten. Am Besten vermutlich auch als Konstante so wie im BASICtext ablegen, oder wenn's richtig schick werden soll, als externes File einlesen, dann kann man da nämlich mit einem Texteditor prima dran rumbasteln und dann per Routine abspielen. In dem Fall per ASSIGN - RESET - READ - CLOSE (oder alternativ mit BLOCKREAD) in eine Variable einlesen.

Hoffe die Links helfen bißchen weiter. Gruß.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »ThoralfAsmussen« (27. Oktober 2015, 12:30)


7

Dienstag, 27. Oktober 2015, 12:30

Ich verweiss da mal auf folgenden Thread: Ports mit Turbo Pascal abfragen

lol - seh' gerade, dass der Thread ja von Dir gestartet worden ist - dann kennst Du das PDF ja schon und wie die weiteren Beiträge zeigen, scheint da ja sehr viel von dem, was Du benötugst drin zu stehen - also ruhig mal genauer durchlesen.

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

8

Dienstag, 27. Oktober 2015, 13:16

Es freut mich, dass ich wieder so schnell einige Antworten und Hinweise bekommen habe, vielen Dank!
Ja, ich werde mich mit dem Dokument und euren Hinweisen mal auseinandersetzen und ein bißchen rumprobieren.

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

9

Dienstag, 27. Oktober 2015, 22:04

So, nun habe ich mal versucht den Code in Turbo Pascal zu übertragen. Leider tritt schon bei der Compilierung in Zeile 53 ein Fehler auf (Fehler 53). Auch ansonsten ist mir noch einiges unklar: den Variablen t und c habe ich zwar Werte zugewiesen, aber diese muss ich noch irgendwie zur Sounderzeugung nutzen, oder sehe ich das falsch?


Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Program PCWMUSIC;
TYPE	arr = ARRAY[0..24] OF INTEGER;
    	oktaven = ARRAY[0..14] OF INTEGER;

CONST   tval : arr =(3324,3132,2961,2789,2636,2485,2350,2227,
                 	2098,1994,1863,1770,1655,1564,1473,1391,
                 	1311,1258,1167,1101,1039,979,924,877,819);
    	cps :  arr =(131,139,147,156,165,175,185,196,
                 	208,220,233,247,262,277,294,311,
                 	330,349,370,392,415,440,466,493,524);	
    	note1 : oktaven=(0,2,4,5,7,9,11,12,14,16,17,19,21,23,24);
    	duration1: oktaven=(4,1,1,1,1,1,1,4,1,1,1,1,1,1,4);

Var 	i,j,scale,pause:	Integer;
    	note,duration:  	Integer;
    	t,c:            	Integer;
    	tune:           	String[60];

Procedure Noten;
Var p,r,rest,oct,Code:  	Integer;
	n:                  	Char;
Begin
	p:=0;
	While p<Length(tune) Do Begin
    	n:=Copy(tune,p+1,1);
    	If n='R' Then Begin
        	p:=p+1;
        	Val(Copy(tune,p+1,1),rest,Code);
        	For r:=0 To rest*25 Do Begin End; (* evtl. durch Delay ersetzen *)
    	End
    	Else If n='O' Then Begin
        	p:=p+1;
        	Val(Copy(tune,p+1,1),oct,Code);
    	End
    	Else Begin
        	note:=Pos(n,'D_EF_G_A_BC')-1;
        	If oct=2 Then note:=note+12;
        	IF Copy(tune,p+2,1)='#' Then note:=note+1;
        	IF Copy(tune,p+2,1)='b' Then note:=note-1;
        	p:=p+1;
        	Val(Copy(tune,p+1,1),duration,Code);
        	t:=tval[note];
        	c:=cps[note] DIV 10 * duration;
        	(*CALL psound(t%,c%)*)
    	End;
    	p:=p+1;
	End;
End;

Procedure Maschinencode;
Var
Begin
	Inline($e5/$d5/$c5/$dd/$e5/$4e/$23/$46/$eb/$5e/$23/
       	$56/$69/$60/$cd/$1b/$cb/$3e/$0c/$d3/$f8/$dd/
       	$e1/$c1/$d1/$e1/$c9/$f3/$7d/$cb/$3d/$cb/$3d/
       	$2f/$e6/$03/$4f/$06/$00/$dd/$21/$30/$cb/$dd/
       	$09/$3e/$0b/$00/$00/$00/$04/$0c/$0d/$20/$fd/
       	$0e/$3f/$05/$20/$f8/$3c/$fe/$0d/$20/$02/$3d/
       	$3d/$d3/$f8/$44/$4f/$fe/$0b/$20/$09/$7a/$b3/
       	$28/$09/$79/$4d/$1b/$dd/$e9/$4d/$0c/$dd/$e9/
       	$fb/$c9/$0d/$0a/$43/$42/$34/$32/$20/$6d/$6f/
       	$64/$75/$6c/$61/$09/$43/$42/$35/$33/$20/$6c/
       	$70/$32/$09/$43/$42/$35/$37/$20/$65/$78/$69/
       	$74/$09/$1a/$c9/$74/$09/$1a/$00/$00/$00/$00);
	(*address:=&HCB00;
	FOR i=1 TO 12 Do Begin
    	sum:=0;*)
    	(*READ mcode$,check$*)
    	(*j:=1;
    	While j<21 Do Begin
        	Val('&H'+Copy(mcode,j,2),byt,Code);
        	mem[address]:=byt;
        	sum:=sum+byt;
        	address:=address+1;
        	j:=j+2;
    	End;
	End;*)
	(*520 psound=&HCB00	*)
End;

Begin
	Procedure Maschinencode;
	WriteLN('Die zwei Oktaven');
	For scale:=0 to 14 Do Begin
    	t:=tval[note1[scale]];
    	c:=cps[note1[scale]] DIV 8 * duration1[scale];
    	(*150 CALL psound(t%,c%)*)
	End;
	For pause:=0 to 500 Do Begin End; (* evtl. durch Delay ersetzen *)
	WriteLN;
	WriteLN('Melodie:');
	WriteLN('Rule Britannia!');
	For repaat:=0 to 1 Do Begin
    	tune:='O2E8E3F3F6E3F4E1D3O1C3B9B3O2G5F5E1D1E1F1G3F3E6D6O1C9';
    	Procedure Noten; 
	End;
End.

Georg

Fortgeschrittener

  • »Georg« ist männlich

Beiträge: 414

Wohnort: Bergisch Gladbach Bensberg

Lieblingscomputer: Sonstige :-)

  • Nachricht senden

10

Mittwoch, 28. Oktober 2015, 01:04

Hallo,

ohne mich jetzt zu später Stunde zu tief in Dein Problem einarbeiten zu wollen, kann ich zumindest ein paar syntaktische Hinweise geben:

Zeile 51: Mit var leitest du eine Variablendeklaration ein, ergo erwartet der Compiler eine Variable, statt dessen kommt begin. Also var weglassen.

Zeile 82 und 95: Prozeduren rufst du einfach mit Namen auf, ohne das Wort procedure. Und den Ersatz für die Prozedur psound musst du natürlich auch an der entsprechenden Stellen aufrufen, also Zeile 87 statt 82. In Basic wird mit der Hilfsprozedur der Maschinecode in den Speicher "gepoked" - das ist hier nicht nötig. Der Maschinecode ist quasi automatisch in der Prozedur drin...

Bei Deinen Variablendeklaration t und c wird's schwierig, weil die als Parameter an die Soundprozedur übergeben werden müssen. Höchstwahrscheinlich unterscheiden sich die Parameter-Übergabemechanismen von TP und BASIC aber, so dass das nicht ohne Anpassungen klappen wird.
Weiterhin erwartet der Maschinecode, an einer speziellen Adresse zu liegen; auch das kann dir Probleme bereiten.

Georg

Georg

Fortgeschrittener

  • »Georg« ist männlich

Beiträge: 414

Wohnort: Bergisch Gladbach Bensberg

Lieblingscomputer: Sonstige :-)

  • Nachricht senden

11

Mittwoch, 28. Oktober 2015, 01:36

Ich habe jetzt doch etwas genauer in den Maschinecode geschaut - anfangs werden wohl die Register gesichert, dann wird (wenn ich nicht irre, lange ist's her) u.a. eine Subroutine an Adresse 0xcb1b angesprungen, kurz danach die Register zurückgelesen und die gesamte Routine mit RET verlassen.

Das ist schon so eine Sache, die nicht funktionieren kann, weil die Prozedur ja irgendwo liegt, aber nicht an Adresse 0xcb00. Ergo findet sich an Adresse 0xcb1b nicht die gewünschte Subroutine.

Ich würde die gesamte Routine disassemblieren, die Sprungadressen bei Bedarf mithilfe des Adresszeigers (location content, Asterisk) berechnen und die Parameter t und c über ihre Namen referenzieren (was in TP ja recht elegant ging), wo sie im Original vermutlich über feste oder relative Adressen gefunden werden.

Georg

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

12

Mittwoch, 28. Oktober 2015, 09:36

Hallo Georg,

vielen Dankfür Deine Unterstützung. Die formalen Fehler habe ich schnell behoben, das Programm lässt sich nun auch compilieren. Wird das Programm ausgeführt, bleibt es innerhalb der ersten Zählschleife hängen. Ich füge den aktuellen Stand mal als Anlage bei.

Was jedoch Dein zweites Posting angeht, so muss ich zugeben, dass ich es nicht verstehe. Ich kenne mich leider weder mit Assembler noch mit dem Adresszeiger aus. :wacko:


@ChaosRom: Die Befehle aus Kapitel 19 des Reference Manual kann ich leider nicht nutzen, da ich mit CP/M plus arbeite. Der Sound-Befehl steht mir somit nicht zur Verfügung.


Viele Grüße,
Marcus
»sucram« hat folgende Datei angehängt:
  • PCWMUSIK.zip (1,38 kB - 53 mal heruntergeladen - zuletzt: 30. August 2017, 12:10)

Beiträge: 688

Wohnort: Dresden (nahebei)

Lieblingscomputer: Acorn RISC OS + +4

  • Nachricht senden

13

Donnerstag, 29. Oktober 2015, 12:14

Was er meint ist eigentlich nicht schwer: Deine Soundroutine enthält ja als Maschinencode irgendwelche Prozessorbefehle, die hintereinander abgearbeitet werden. Wenn da aber eine Sprunganweisung dabei ist, dann steht da im Normalfall eine fixe Adresse an die der Prozessor dann "springt" und dort weitere Befehle abarbeitet. Das funktioniert auch prima, solange der Maschinencode an der richtigen Stelle im Speicher liegt - in Deinem Fall ab Adresse &CB00.
Das müßtest Du also sicherstellen, damit der Code so funktioniert, wie er da abgedruckt ist.

Deine Subroutine, die das Ablegen der Bytes in den Speicher übernimmt, hat aber keinerlei Anweisungen, wo man festlegt, wo der Code landen soll. Er wird also "irgendwo", nämlich da wo das Pascalprogramm gerade hin"compiliert" wird, im Speicher liegen. Nur mit einer völlig zu vernachlässigender Wahrscheinlichkeit wird er zufällig gerade bei &CB00 starten - und genau aus diesem Grund, springt dann eine Sprunganweisung, die z.B. nach &CB15 springt, in irgendwelchen fremden Code, oder in eine Wüste aus lauter &00 Bytes, oder irgendwas anderes - aber auf jeden Fall nicht dahin, wo die eigentlich Soundroutine weitergeht. Die Folge: Der Rechner friert ein, oder das Programm stürzt ab.

Du hast zwei Möglichkeiten das zu umgehen:

a.) Die Bytes definiert beginnend bei &CB00 ablegen, wenn das irgendwie per Compileroption oder anders möglich ist. Dazu muß aber vorher sichergestellt werden, daß da nicht was anderes schon "rumliegt". Der Vorteil ist: Die Routine kann so bleiben, wie sie ist, da die Adressen "passen"

b.) Versuchen zu verstehen, was die Routine eigentlich macht. Dazu müßte man sie sinnvollerweise erstmal vom Maschinencode in Assembler "übersetzen", d.h. sie Dissassemblieren, damit sie vernünftig lesbar wird. Dann kann man schauen, ob Kommandos auftauchen, die an bestimmte Speicherstellen gebunden sind und nachfolgend versuchen diese Anweisungen so umzuschreiben, daß der Code an beliebiger Stelle im Speicher liegen kann.
Wenn Du das mit dem Dissassemblieren machst und hier postest, könnte ich mir vorstellen, daß sich jemand findet, der was dazu weiß und Vorschläge hat. Den Byteblock dagegen wird sich vermutlich, so wie er ist, keiner angucken. (Wobei das auch geht, es gab/gibt da auf jeden Fall Leute, die sowas konnten/können und direkt aus dem Zahlenblock heraus sagen können, was das Programm macht - also Maschinensprache direkt lesen können. Das ist aber ziemlich selten.) (Was man sagen kann, ist, daß das Byte &CB ein paarmal auftaucht, weshalb da möglicherweise wirklich Sprünge innerhalb der Routine dabei sind; kann aber auch was anderes bedeuten.)

Beiträge: 688

Wohnort: Dresden (nahebei)

Lieblingscomputer: Acorn RISC OS + +4

  • Nachricht senden

14

Donnerstag, 29. Oktober 2015, 13:37

Quellcode

1
2
3
4
5
6
7
8
9
10
~/_DOWNLOAD/PCWmusic$ hd ass
00000000  e5 d5 c5 dd e5 4e 23 46  eb 5e 23 56 69 60 cd 1b  |.....N#F.^#Vi`..|
00000010  cb 3e 0c d3 f8 dd e1 c1  d1 e1 c9 f3 7d cb 3d cb  |.>..........}.=.|
00000020  3d 2f e6 03 4f 06 00 dd  21 30 cb dd 09 3e 0b 00  |=/..O...!0...>..|
00000030  00 00 04 0c 0d 20 fd 0e  3f 05 20 f8 3c fe 0d 20  |..... ..?. .<.. |
00000040  02 3d 3d d3 f8 44 4f fe  0b 20 09 7a b3 28 09 79  |.==..DO.. .z.(.y|
00000050  4d 1b dd e9 4d 0c dd e9  fb c9 0d 0a 43 42 34 32  |M...M.......CB42|
00000060  20 6d 6f 64 75 6c 61 09  43 42 35 33 20 6c 70 32  | modula.CB53 lp2|
00000070  09 43 42 35 37 20 65 78  69 74 09 1a c9 74 09 1a  |.CB57 exit...t..|
00000080  00 00 00 00                                       |....|


Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
~/_DOWNLOAD/PCWmusic$ z80dasm -altg 0xcb00 ass
; z80dasm 1.1.0
; command line: z80dasm -altg 0xcb00 ass

	org	0cb00h

	push hl			;cb00	e5 	. 
	push de			;cb01	d5 	. 
	push bc			;cb02	c5 	. 
	push ix		;cb03	dd e5 	. . 
	ld c,(hl)			;cb05	4e 	N 
	inc hl			;cb06	23 	# 
	ld b,(hl)			;cb07	46 	F 
	ex de,hl			;cb08	eb 	. 
	ld e,(hl)			;cb09	5e 	^ 
	inc hl			;cb0a	23 	# 
	ld d,(hl)			;cb0b	56 	V 
	ld l,c			;cb0c	69 	i 
	ld h,b			;cb0d	60 	` 
	call sub_cb1bh		;cb0e	cd 1b cb 	. . . 
	ld a,00ch		;cb11	3e 0c 	> . 
	out (0f8h),a		;cb13	d3 f8 	. . 
	pop ix		;cb15	dd e1 	. . 
	pop bc			;cb17	c1 	. 
	pop de			;cb18	d1 	. 
	pop hl			;cb19	e1 	. 
	ret			;cb1a	c9 	. 
sub_cb1bh:
	di			;cb1b	f3 	. 
	ld a,l			;cb1c	7d 	} 
	srl l		;cb1d	cb 3d 	. = 
	srl l		;cb1f	cb 3d 	. = 
	cpl			;cb21	2f 	/ 
	and 003h		;cb22	e6 03 	. . 
	ld c,a			;cb24	4f 	O 
	ld b,000h		;cb25	06 00 	. . 
	ld ix,lcb30h		;cb27	dd 21 30 cb 	. ! 0 . 
	add ix,bc		;cb2b	dd 09 	. . 
	ld a,00bh		;cb2d	3e 0b 	> . 
	nop			;cb2f	00 	. 
lcb30h:
	nop			;cb30	00 	. 
	nop			;cb31	00 	. 
	inc b			;cb32	04 	. 
	inc c			;cb33	0c 	. 
lcb34h:
	dec c			;cb34	0d 	. 
	jr nz,lcb34h		;cb35	20 fd 	  . 
	ld c,03fh		;cb37	0e 3f 	. ? 
	dec b			;cb39	05 	. 
	jr nz,lcb34h		;cb3a	20 f8 	  . 
	inc a			;cb3c	3c 	< 
	cp 00dh		;cb3d	fe 0d 	. . 
	jr nz,lcb43h		;cb3f	20 02 	  . 
	dec a			;cb41	3d 	= 
	dec a			;cb42	3d 	= 
lcb43h:
	out (0f8h),a		;cb43	d3 f8 	. . 
	ld b,h			;cb45	44 	D 
	ld c,a			;cb46	4f 	O 
	cp 00bh		;cb47	fe 0b 	. . 
	jr nz,lcb54h		;cb49	20 09 	  . 
	ld a,d			;cb4b	7a 	z 
	or e			;cb4c	b3 	. 
	jr z,lcb58h		;cb4d	28 09 	( . 
	ld a,c			;cb4f	79 	y 
	ld c,l			;cb50	4d 	M 
	dec de			;cb51	1b 	. 
	jp (ix)		;cb52	dd e9 	. . 
lcb54h:
	ld c,l			;cb54	4d 	M 
	inc c			;cb55	0c 	. 
	jp (ix)		;cb56	dd e9 	. . 
lcb58h:
	ei			;cb58	fb 	. 
	ret			;cb59	c9 	. 
	dec c			;cb5a	0d 	. 
	ld a,(bc)			;cb5b	0a 	. 
	ld b,e			;cb5c	43 	C 
	ld b,d			;cb5d	42 	B 
	inc (hl)			;cb5e	34 	4 
	ld (06d20h),a		;cb5f	32 20 6d 	2   m 
	ld l,a			;cb62	6f 	o 
	ld h,h			;cb63	64 	d 
	ld (hl),l			;cb64	75 	u 
	ld l,h			;cb65	6c 	l 
	ld h,c			;cb66	61 	a 
	add hl,bc			;cb67	09 	. 
	ld b,e			;cb68	43 	C 
	ld b,d			;cb69	42 	B 
	dec (hl)			;cb6a	35 	5 
	inc sp			;cb6b	33 	3 
	jr nz,$+110		;cb6c	20 6c 	  l 
	ld (hl),b			;cb6e	70 	p 
	ld (04309h),a		;cb6f	32 09 43 	2 . C 
	ld b,d			;cb72	42 	B 
	dec (hl)			;cb73	35 	5 
	scf			;cb74	37 	7 
	jr nz,$+103		;cb75	20 65 	  e 
	ld a,b			;cb77	78 	x 
	ld l,c			;cb78	69 	i 
	ld (hl),h			;cb79	74 	t 
	add hl,bc			;cb7a	09 	. 
	ld a,(de)			;cb7b	1a 	. 
	ret			;cb7c	c9 	. 
	ld (hl),h			;cb7d	74 	t 
	add hl,bc			;cb7e	09 	. 
	ld a,(de)			;cb7f	1a 	. 
	nop			;cb80	00 	. 
	nop			;cb81	00 	. 
	nop			;cb82	00 	. 
	nop			;cb83	00 	. 
Warning: Code might not be 8080 compatible!


Ich war mal so frei, das in Textform zu bringen, vielleicht erhöht das die Kommentarzahl ein wenig. Allerdings "vorlesen" müßte es jemand anders.

Bei "call sub_cb1bh" steht die Verzweigung. Und die springt direkt an die Adresse &CB1B - und spätestens da schmiert Dir dann das Programm weg.
Alles hinter &CB5A ist irgendwie Text und kein Programm mehr, sieht zumindest so aus; was auch immer das da macht.

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

15

Donnerstag, 29. Oktober 2015, 14:26

Herzlichen Dank für die Mühe! Es wäre wirklich schön, wenn jemand eine Idee hätte, wie man den Mischinencode an die betreffende Stelle legen könnte, sofern das überhaupt in TP möglich ist. Wenn ich es richtig verstehe kann es natürlich sein, dass der betreffende Bereich bereits anderweitig z.B. durch TP selbst belegt wird. In dem Fall wird das vermeintlich kleine Problem dann doch etwas komplexer.

Georg

Fortgeschrittener

  • »Georg« ist männlich

Beiträge: 414

Wohnort: Bergisch Gladbach Bensberg

Lieblingscomputer: Sonstige :-)

  • Nachricht senden

16

Donnerstag, 29. Oktober 2015, 19:05

Hallo,

Du hast eine ganze Reihe von Problemen. Zum einen die schon genannte Subroutine, die per fixer Adresse angesprungen wird (im Gegensatz zu den relativen Sprüngen JR, die nur den Abstand angeben, also von der echten Adresse unabhängig sind). Andererseits wird in IX ebenfalls eine feste Sprungadresse abgelegt (und noch modifiziert) - auch das musst Du anpassen. Und schließlich werden am Anfang mit der ganzen Bastelei um HL und DE die Parameter (vermutlich vom Stack) gelesen - das geht bei Deiner Programmierung auch nicht, weil Du globale Variablen verwendest.

Ein Ablegen des Codes an die feste Adresse würde ich Dir nicht empfehlen - ich kenne jetzt die Speicherverwaltung Deines Rechners unter CP/M nicht, aber es ist eher zweifelhaft, dass das klappt. Wobei das Problem mit den Parametern immer bestehen bleibt.

Das wird also schwierig ...

Für mehr Hilfe fehlt mir gerade leider die Zeit :(

Georg

Georg

Fortgeschrittener

  • »Georg« ist männlich

Beiträge: 414

Wohnort: Bergisch Gladbach Bensberg

Lieblingscomputer: Sonstige :-)

  • Nachricht senden

17

Freitag, 30. Oktober 2015, 02:05

So, jetzt kommen wieder ein paar weitere Details.
Zunächst gebe ich Thoralf recht, alles hinter 0CB59H ist überflüssig. Bleibt das hier als Ausgangsbasis:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
	org	0cb00h

	push hl			;cb00	e5 	. 
	push de			;cb01	d5 	. 
	push bc			;cb02	c5 	. 
	push ix			;cb03	dd e5 	. . 
	ld c,(hl)			;cb05	4e 	N 
	inc hl			;cb06	23 	# 
	ld b,(hl)			;cb07	46 	F 
	ex de,hl			;cb08	eb 	. 
	ld e,(hl)			;cb09	5e 	^ 
	inc hl			;cb0a	23 	# 
	ld d,(hl)			;cb0b	56 	V 
	ld l,c			;cb0c	69 	i 
	ld h,b			;cb0d	60 	` 
	call sub_cb1bh		;cb0e	cd 1b cb 	. . . 
	ld a,00ch			;cb11	3e 0c 	> . 
	out (0f8h),a		;cb13	d3 f8 	. . 
	pop ix			;cb15	dd e1 	. . 
	pop bc			;cb17	c1 	. 
	pop de			;cb18	d1 	. 
	pop hl			;cb19	e1 	. 
	ret				;cb1a	c9 	. 

sub_cb1bh:
	di				;cb1b	f3 	. 
	ld a,l			;cb1c	7d 	} 
	srl l				;cb1d	cb 3d 	. = 
	srl l				;cb1f	cb 3d 	. = 
	cpl				;cb21	2f 	/ 
	and 003h			;cb22	e6 03 	. . 
	ld c,a			;cb24	4f 	O 
	ld b,000h			;cb25	06 00 	. . 
	ld ix,lcb30h		;cb27	dd 21 30 cb 	. ! 0 . 
	add ix,bc			;cb2b	dd 09 	. . 
	ld a,00bh			;cb2d	3e 0b 	> . 
	nop				;cb2f	00 	. 
lcb30h:
	nop				;cb30	00 	. 
	nop				;cb31	00 	. 
	inc b				;cb32	04 	. 
	inc c				;cb33	0c 	. 
lcb34h:
	dec c			;cb34	0d 	. 
	jr nz,lcb34h		;cb35	20 fd 	  . 
	ld c,03fh			;cb37	0e 3f 	. ? 
	dec b			;cb39	05 	. 
	jr nz,lcb34h		;cb3a	20 f8 	  . 
	inc a				;cb3c	3c 	< 
	cp 00dh			;cb3d	fe 0d 	. . 
	jr nz,lcb43h		;cb3f	20 02 	  . 
	dec a			;cb41	3d 	= 
	dec a			;cb42	3d 	= 
lcb43h:
	out (0f8h),a		;cb43	d3 f8 	. . 
	ld b,h			;cb45	44 	D 
	ld c,a			;cb46	4f 	O 
	cp 00bh			;cb47	fe 0b 	. . 
	jr nz,lcb54h		;cb49	20 09 	  . 
	ld a,d			;cb4b	7a 	z 
	or e				;cb4c	b3 	. 
	jr z,lcb58h		;cb4d	28 09 	( . 
	ld a,c			;cb4f	79 	y 
	ld c,l			;cb50	4d 	M 
	dec de			;cb51	1b 	. 
	jp (ix)			;cb52	dd e9 	. . 
lcb54h:
	ld c,l			;cb54	4d 	M 
	inc c				;cb55	0c 	. 
	jp (ix)			;cb56	dd e9 	. . 
lcb58h:
	ei				;cb58	fb 	. 
	ret				;cb59	c9 	.

  • Die ersten 4 Zeilen des Codes sichern die Register auf den Stack
  • Die nächsten 10 Zeilen laden das Word, auf das HL zeigt, nach HL, und das Wort, auf das DE zeigt, nach DE. Das sind offenbar die beiden Parameter, die anscheinend doch nicht auf dem Stack liegen. Von der Art, wie Dein Basic den Aufruf call psound(t%, c%) umsetzt, habe ich keine Ahnung. Hier muss auf jeden Fall gearbeitet werden!
  • Anschließend wird die eigentliche Routine per Call mit absoluter Adresse angesprungen. Baustelle!
  • Danach wird noch ein 0Ch auf dem Port 0F8h ausgegeben, die Register restauriert und zurück ins Hauptprogramm gesprungen.
  • Die eigentliche Routine selber macht eine Menge Rechnerei und Schleifen mit den verschiedensten Lauflängen - im Wesentlichen unkritisch für Dich bis auf den Sprung JP (IX), der wieder mit absoluten Adressen arbeitet. Maßgeblich ist die Zeile LD IX,0CB30h - diese Adresse muss ebenfalls angepasst werden.
  • Die Ausgabe an den Port 0F8h wird wohl stimmen, wenn das ursprüngliche BASIC-Programm ebenfalls für Deinen Rechner bestimmt war.


Jetzt ein paar Lösungsansätze (weitere Informationen auf Seite 274ff im schon genannten Manual):

Auf Deine Variablen kannst Du in Inline-Befehlen relativ einfach zugreifen, etwa so:

Quellcode

1
2
3
4
5
6
7
8
9
10
procedure Sound;
begin
  inline($e5/          { PUSH HL            }
         $d5/          { PUSH DE            }
         $c5/          { PUSH BC            }
         $dd/$e5/      { PUSH IX            }
         $2a/C/        { LD HL,(Variable C) }
         $eb/          { EX DE,HL           }
         $2a/T/        { LD HL,(Variable T) }
             .....


Damit wäre der Inhalt der Variable C in DE und der Inhalt von T in HL. So ist es wohl gedacht - evtl. muss es umgekehrt sein, das hängt vom Mechansimus des BASIC ab.
Dieses Konstrukt sollte mit etwas Glück den gesamten Part von 0CB05H bis 0CB0Dh ersetzen.

Als nächstes ist die Kalkulation der Sprungadressen mit dem Location Counter dran, das sollte so gehen:

Die Sprungweite von der Position, wo die Zieladresse steht bis zur Zieladresse selber ist im Originalcode 12 Byte (dezimal), von Adresse 0CB0Fh bis 0CB1Bh. Ergo müsste der Sprungbefehl so aussehen:

Quellcode

1
2
3
4
5
...
inline(
... 
$cd/*+12/   { Call  Subroutine }
...


Analog die Berechnung für den Ladebefehl:

Quellcode

1
2
3
4
5
...
$06/$00/        { LD B,0           }
$dd/$21/*+7/    { LD IX,Sprungziel }
$dd/$09/        { ADD IX,BC        }
...


Da ich den Verdacht habe, dass Du eine Inline-Routine nicht mit RET verlassen darfst (das will die selber machen), müsstest Du eigentlich anstatt des RET an der (alten) Adresse 0CB1Ah einen Sprung an das Ende der gesamten Routine machen. Alternativ sparst Du Dir die interne Subroutine und packst einfach alles, was vorher von 0CB1Bh bis 0CB58h stand (ohne den RET-Befehl) an die Stelle des Calls an Adresse 0CB0Eh. Das heißt, Du ersetzt den Aufruf der Routine durch die Routine selber. Dann lässt Du am Ende nach den POPs einfach den RET-Befehl ebenfalls weg, sparst Dir eine Adressrechnerei und alles müsste funktionieren. Die Sprünge innerhalb der Routine sind alle relativ, ebenso wie inzwischen auch der Ladebefehl. Das sollte alles keine Probleme machen.


Inzwischen weiß ich übrigens auch, wie Du in TP Daten (und damit auch Maschinencode) an eine feste Adresse legen kannst. Du kannst eine Variable mit der Direktive absolute deklarieren und dabei die Adresse angeben, wo die Variable angelegt werden soll. Hier wäre es also möglich, z.B. einen array of byte der richtigen Länge an der Adresse 0CB00H anzulegen und die Variable dann mit diesen Codes zu füllen.
Allerdings weiß ich im Moment keinen eleganten Weg dafür, der brutale geht so:

Quellcode

1
2
3
4
5
6
7
8
var Maschinencode: array [0..x] of byte absolute $cb00;
...
  Maschinencode[0] := $e5;
  Maschinencode[1] := $d5;
  Maschinencode[2] := $c5;
  Maschinencode[3] := $dd;
  Maschinencode[4] := $e5;
..usw..


Der Aufruf ist dann aber nicht mehr per Prozeduraufruf möglich, sondern nur noch über eine eigene Inline-Prozedur:

Quellcode

1
2
3
4
procedure Sound;
begin
   inline($cd/$cb00);   { CALL 0CB00h }
end;

Das wäre also noch eine Möglichkeit - da Du aber den Zugriff auf Deine Variablen benötigst (was elegant nur innerhalb des Inlines geht), müsstest Du diesen Zugriff und damit auch die PUSHs und POPs mit in diese Sound-Prozedur packen; vom ursprünglichen Maschinencode bleibt dann nur noch die innere Routine, die Du dann auch direkt anspringen musst. Dazu wird dann natürlich die absolute Variable an die Adresse 0CB1Bh gelegt und nur noch mit dem Code der inneren Routine gefüllt.

Ob das funktioniert hängt halt von Deiner Speicherverwaltung ab; wenn Du Pech hast, knallt das gewaltig. Auf jeden Fall vor jedem Probelauf Quelltexte sichern ;)


Das ganze ist natürlich nur eine Folge von Hinweisen; ausarbeiten (und testen und auf die Nase fallen und Details rausfinden etc.) musst Du selber - vor allem, weil ich hier nur theoretisch dran gehen und nichts ausprobieren kann.

Trotzdem viel Erfolg!

Georg

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

18

Freitag, 30. Oktober 2015, 11:22

Hallo Georg,

vielen Dank für Deine Hilfe! Ich werde heute Abend und am Sonntag versuchen weiterzukommen...

Viele Grüße,
Marcus

sucram

Anfänger

  • »sucram« ist männlich
  • »sucram« ist der Autor dieses Themas

Beiträge: 44

Wohnort: 46487 Büderich

Lieblingscomputer: Schneider Joyce bzw. Amstrad PCW

  • Nachricht senden

19

Freitag, 6. November 2015, 15:09

:S Leider bekomme ich es nicht hin. Ich habe einiges ausprobiert, mal piept der Rechner und hängt sich auf, ein anderes Mal hängt er sich ohne Ton auf oder er steigt nur aus Turbo Pascal aus.

Dennoch nochmals vielen Dank an alle, die versucht haben mir zu helfen! Auch wenn ich dieses Problem nicht gelöst habe, so habe ich dennoch einiges gelernt.

funkenzupfer

Z80 Versteher

  • »funkenzupfer« ist männlich

Beiträge: 690

Wohnort: in der Nähe von 51°04'27.3"N 6°28'02.3"E

Lieblingscomputer: Video Genie System EG3003

  • Nachricht senden

20

Sonntag, 8. November 2015, 15:05

Wo liegt den das Problem? Im Maschinencode selber oder im Aufruf des selbigen?
;------------------------------------
;----- ENABLE NMI INTERRUPTS
(aus: IBM BIOS Source Listing)

Thema bewerten