; ASMCURVE.ASM: Zeichnet einen Ellipsenbogen ; ; Autor: Michael Schuschk ; edited by Frank Riemenschneider ; ; Eingabe: AX = X-Koordinate Ellipsenmittelpunkt (0-239) ; BX = Y-Koordinate Ellipsenmittelpunkt (0-63) ; CX = Radius in X-Richtung (0-255) ; DX = Radius in Y-Richtung (0-255) ; ES = Anfangswinkel in Grad (0-359ø) ; SI = Endwinkel in Grad (0-360ø) ; Ausgabe: keine DATASEG ; Ben”tigte Variable x dw ? ; X-Koordinate y dw ? ; Y-Koordinate xr dw ? ; X-Radius yr dw ? ; Y-Radius xoff dw ? ; X-Offset yoff dw ? ; Y-Offset zaehl1 dw ? ; Z„hler 1 zaehl2 dw ? ; Z„hler 2 xm dw ? ; X-Koordinate Mittelpunkt anqua dw ? ; Anfangsquadrant endqua dw ? ; Endquadrant anpunkt dw ? ; Anfangspunkt endpunkt dw ? ; Endpunkt offtab1 db 400 dup (?) ; Offset-Tabellen offtab2 db 400 dup (?) extrn costab : DWORD extrn ArcStartX : DWORD extrn ArcStartY : DWORD extrn ArcEndX : DWORD extrn ArcEndY : DWORD CODESEG ; Koordinate des Start- und Endpunktes des Ellipsenbogens berechnen MACRO CalcPoints StartQuad, EndQuad IFIDNI , <1> mov bx, 394 sub bx, [anpunkt] ENDIF IFIDNI , <2> mov bx, [anpunkt] ENDIF IFIDNI , <3> mov bx, 394 sub bx, [anpunkt] ENDIF IFIDNI , <4> mov bx, [anpunkt] ENDIF xor ch, ch mov dh, ch mov cl, [offtab1+bx] mov dl, [offtab2+bx] IFIDNI , <1> add cx, [xm] mov [WORD ArcStartX], cx mov cx, [y] sub cx, dx mov [WORD ArcStartY], cx ENDIF IFIDNI , <2> add cx, [xm] mov [WORD ArcStartX], cx add dx, [y] mov [WORD ArcStartY], dx ENDIF IFIDNI , <3> mov ax, [xm] sub ax, cx mov [WORD ArcStartX], ax add dx, [y] mov [WORD ArcStartY], dx ENDIF IFIDNI , <4> mov ax, [xm] sub ax, cx mov [WORD ArcStartX], ax mov cx, [y] sub cx, dx mov [WORD ArcStartY], cx ENDIF IFIDNI , <1> mov bx, 394 sub bx, [endpunkt] ENDIF IFIDNI , <2> mov bx, [endpunkt] ENDIF IFIDNI , <3> mov bx, 394 sub bx, [endpunkt] ENDIF IFIDNI , <4> mov bx, [endpunkt] ENDIF xor ch, ch mov dh, ch mov cl, [offtab1+bx] mov dl, [offtab2+bx] IFIDNI , <1> add cx, [xm] mov [WORD ArcEndX], cx mov cx, [y] sub cx, dx mov [WORD ArcEndY], cx ENDIF IFIDNI , <2> add cx, [xm] mov [WORD ArcEndX], cx add dx, [y] mov [WORD ArcEndY], dx ENDIF IFIDNI , <3> mov ax, [xm] sub ax, cx mov [WORD ArcEndX], ax add dx, [y] mov [WORD ArcEndY], dx ENDIF IFIDNI , <4> mov ax, [xm] sub ax, cx mov [WORD ArcEndX], ax mov cx, [y] sub cx, dx mov [WORD ArcEndY], cx ENDIF ENDM ; Quadranten zeichnen MACRO QuadLoop Quad, Index1, Index2 xor ch, ch mov dh, ch LoopQ&Quad: mov bx, [zaehl&Index1] mov cl, [offtab1+bx] ; X-Offset holen mov dl, [offtab2+bx] ; Y-Offset holen mov ax, [xm] ; X-Koordinate Mittelpunkt holen IFIDNI , <1> add ax, cx ; x = xm + xoff mov bx, [y] ; Y-Koordinate holen sub bx, dx ; y = y - yoff ENDIF IFIDNI , <2> add ax, cx ; x = xm + xoff mov bx, [y] add bx, dx ; y = y + yoff ENDIF IFIDNI , <3> sub ax, cx ; x = xm - xoff mov bx, [y] add bx, dx ; y = y + yoff ENDIF IFIDNI , <4> sub ax, cx ; x = xm - xoff mov bx, [y] sub bx, dx ; y = y - yoff ENDIF call AsmPlot ; Punkt setzen mov ax, [zaehl&Index1] cmp ax, [zaehl&Index2] ; alle Punkte gesetzt? je ExitLoopQ&Quad ; Ja -!> Beenden inc ax ; Z„hler erh”hen mov [zaehl&Index1], ax jmp LoopQ&Quad ExitLoopQ&Quad: ret ENDM ; Koordinaten holen PROC koor NEAR mov [xm], ax ; X-Koordinate Mittelpunkt mov [y], bx ; Y-Koordinate Mittelpunkt mov [xr], cx ; Radius X-Richtung mov [yr], dx ; Radius Y-Richtung mov ax, es ; Anfanswinkel in AX call rechne ; Anfangswinkel in Anfangsquadranten und ; Anfangspunkt umrechnen mov [anqua], ax ; Anfangsquadrant mov [anpunkt], bx ; Anfangspunkt mov ax, si ; Endwinkel in AX call rechne ; Endwinkel in Endquadranten und ; Endpunkt umrechnen mov [endqua], ax ; Endquadrant mov [endpunkt], bx ; Endpunkt ret ; Umrechnung: Winkel -> Quadrant und Punkt rechne: push ax ; wird sp„ter noch gebraucht mov cx, 90 div cl ; Winkel / 90 xor ah, ah ; Divisionsrest l”schen ; => INT(Winkel / 90) inc al ; Quadrant = INT(Winkel / 90) + 1 mov dx, ax ; Quadrant retten dec al mul cl ; (Quadrant - 1) * 90 pop bx ; Winkel holen push dx sub bx, ax ; Teilwinkel = Winkel - (Quadrant - 1) * 90, ; 0ø <= Teilwinkel < 90ø mov ax, bx mov cx, 395 mul cx ; Teilwinkel * 395, Ergebnis in DX:AX mov cx, 90 div cx ; Punkt = (Teilwinkel * 395) / 90ø mov bx, ax ; Werte in die richtigen Register bringen pop ax ret ; Back to happiness ENDP ; Berechnung von AL * BX / 256 PROC Mult NEAR xchg ax, bx mul bl ; AL * BX REPT 8 shr ax, 1 ; AX 8 mal rechts schieben => AX / 256 ENDM ret ENDP ; Ersten Quadranten zeichnen PROC erster NEAR mov [zaehl1], ax mov [zaehl2], bx mov bx, 394 ; Z„hler setzen sub bx, [zaehl1] ; und invertieren mov [zaehl1], bx mov bx, 394 sub bx, [zaehl2] mov [zaehl2], bx QuadLoop 1, 2, 1 ENDP ; Zweiten Quadranten zeichnen PROC zweiter NEAR mov [zaehl1], ax ; Z„hler setzen mov [zaehl2], bx QuadLoop 2, 1, 2 ENDP ; Dritten Quadranten zeichnen PROC dritter NEAR mov [zaehl1], ax ; Z„hler setzen mov [zaehl2], bx mov ax, 394 sub ax, [zaehl1] ; und invertieren mov [zaehl1], ax mov bx, 394 sub bx, [zaehl2] mov [zaehl2], bx QuadLoop 3, 2, 1 ENDP ; Vierten Quadranten zeichnen PROC vierter NEAR mov [zaehl1], ax ; Z„hler setzen mov [zaehl2], bx QuadLoop 4, 1, 2 ENDP PROC AsmCurve ; Register retten push ax push bx push cx push dx push es push si push di call koor ; Koordinaten zuweisen cmp [anqua], 1 ; Start im 1. Quadranten? jne ausschnitt ; mit erstem Punkt cmp [anpunkt], 0 ; Nur Ellipsenabschnitt zeichnen? jne ausschnitt cmp [endqua], 5 ; Ende wieder im 1. Quadranten? jne ausschnitt ; nur Ellipsenabschnitt cmp [endpunkt], 0 ; Komplette Ellipse zeichnen? jne ausschnitt ; Nein -> Ellipsenabschnitt zeichnen je ganz ; Ja -> komplette Ellipse zeichnen ausschnitt: jmp aussch ; Sprung zum Zeichnen eines Ellipsenabschnitts ; komplette Ellipse zeichnen ganz: mov bx, [xm] ; X-Koordinate Mittelpunkt in x merken push ax mov ax, [y] ; Anfangs- und Endpunktskoordinaten berechnen sub ax, [yr] ; und speichern mov [WORD ArcStartX], bx mov [WORD ArcEndX], bx mov [WORD ArcStartY], ax mov [WORD ArcEndY], ax pop ax mov [x], bx mov [zaehl2], 0 ; Beide Z„hler setzen mov [zaehl1], 394 CircleLoop: mov bx, [zaehl1] xor ah, ah mov al, [BYTE costab+bx] ; Cosinus-Wert in AX mov bx, [xr] ; X-Radius in BX call mult ; AL*xr/256 berechnen mov [xoff], ax ; = x-offset mov bx, [zaehl2] ; Z„hler2 xor ah, ah mov al, [BYTE costab+bx] ; Sinus-Wert holen mov bx, [yr] ; Y-Radius call mult ; AL*yr/256 berechnen mov [yoff], ax ; = y-offset mov ax, [xm] ; X-Koordinate Mittelpunkt in AX add ax, [xoff] ; x = xm + xoff mov bx, [y] ; Y-Koordinate in BX add bx, [yoff] ; y = y + yoff mov cx, bx ; y + yoff in CX retten call AsmPlot ; 1. Punkt setzen mov bx, [y] ; Y-Koordinate in BX sub bx, [yoff] ; y = y - yoff mov dx, bx ; y - yoff in DX retten call AsmPlot ; 2. Punkt setzen mov ax, [xm] ; X-Koordinate Mittelpunkt laden sub ax, [xoff] ; x = xm - xoff mov bx, cx ; y + yoff laden call AsmPlot ; 3. Punkt setzen mov bx, dx ; y - yoff laden call AsmPlot ; 4. Punkt setzen inc [zaehl2] ; Z„hler 1 erh”hen dec [zaehl1] ; Z„hler 2 erniedrigen jne CircleLoop ; n„chsten 4 Punkte berechnen jmp CircleExit1 ; Beide Z„hler gleich -> Beenden ; Ellipsenabschnitt zeichnen aussch: mov [zaehl1], 395 ; Beide Z„hler laden mov [zaehl2], 0 ausloop: mov bx, [zaehl1] ; Tabelle der Offsets in X- und Y-Richtung xor ah, ah ; aufbauen mov al, [BYTE costab+bx] mov bx, [xr] call mult mov bx, [zaehl2] mov [offtab1+bx], al xor ah, ah mov al, [BYTE costab+bx] mov bx, [yr] call mult mov bx, [zaehl2] mov [offtab2+bx], al inc [zaehl2] dec [zaehl1] jne ausloop mov ax, [xm] mov [x], ax mov bx, [anqua] ; Anfangsquadranten laden shl bx, 1 shl bx, 1 ; anqua * 4 add bx, [endqua] ; Endquadranten dazu addieren sub bx, 5 ; 0 <= Indexwert <= 15 shl bx, 1 ; Indexwert * 8 shl bx, 1 shl bx, 1 mov ax, OFFSET jumptab add ax, bx jmp ax jumptab: call s1e1 ; Diese Sprungtabelle ist n”tig, da Assembler- jmp CircleExit1 ; Routinen in Turbo-Pascal keine typisierten nop ; Konstanten verwenden drfen. Sonst k”nnte nop ; man dies wesentlich krzer programmieren. call s1e2 ; Die NOP's dienen nur dazu die Distanz jmp CircleExit1 ; zwischen den Sprungzielen auf 8 Byte aufzu- nop ; weiten, damit die Sprungberechnung einfacher nop ; wird. call s1e3 jmp CircleExit1 nop nop call s1e4 jmp CircleExit1 nop nop call s2e1 jmp CircleExit1 nop nop call s2e2 jmp CircleExit1 nop nop call s2e3 jmp CircleExit1 nop nop call s2e4 jmp CircleExit1 nop nop call s3e1 jmp CircleExit1 nop nop call s3e2 jmp CircleExit1 nop nop call s3e3 jmp CircleExit1 nop nop call s3e4 jmp CircleExit1 nop nop call s4e1 jmp CircleExit1 nop nop call s4e2 jmp CircleExit1 nop nop call s4e3 jmp CircleExit1 nop nop call s4e4 jmp CircleExit1 ; Start im 1., Ende im 1. Quadranten s1e1: CalcPoints 1, 1 mov ax, [anpunkt] mov bx, [endpunkt] cmp ax, bx jle s1e11 mov bx, 394 call erster xor ax, ax jmp s2e1a s1e11: mov bx, [endpunkt] jmp erster ; Start im 1., Ende im 2. Quadranten s1e2: CalcPoints 1, 2 mov ax, [anpunkt] s1e2b: mov bx, 394 call erster xor ax, ax s1e2a: mov bx, [endpunkt] jmp zweiter ; Start im 1., Ende im 3. Quadranten s1e3: CalcPoints 1, 3 mov ax, [anpunkt] s1e3c: mov bx, 394 call erster xor ax, ax s1e3a: mov bx, 394 call zweiter xor ax, ax s1e3b: mov bx, [endpunkt] jmp dritter ; Start im 1., Ende im 4. Quadranten s1e4: CalcPoints 1, 4 mov ax, [anpunkt] s1e4c: mov bx, 394 call erster xor ax, ax s1e4a: mov bx, 394 call zweiter xor ax, ax s1e4b: mov bx, 394 call dritter xor ax, ax s1e4d: mov bx, [endpunkt] jmp vierter ; Start im 2., Ende im 1. Quadranten s2e1: CalcPoints 2, 1 mov ax, [anpunkt] s2e1a: mov bx, 394 call zweiter xor ax, ax s2e1b: mov bx, 394 call dritter xor ax, ax s2e1c: mov bx, 394 call vierter xor ax, ax jmp s1e11 ; Start im 2., Ende im 2. Quadranten s2e2: CalcPoints 2, 2 mov ax, [anpunkt] mov bx, [endpunkt] cmp ax, bx jle s2e22 mov bx, 394 call zweiter xor ax, ax jmp s3e2a s2e22: jmp s1e2a ; Start im 2., Ende im 3. Quadranten s2e3: CalcPoints 2, 3 mov ax, [anpunkt] jmp s1e3a ; Start im 2., Ende im 4. Quadranten s2e4: CalcPoints 2, 4 mov ax, [anpunkt] jmp s1e4a ; Start im 3., Ende im 1. Quadranten s3e1: CalcPoints 3, 1 mov ax, [anpunkt] jmp s2e1b ; Start im 3., Ende im 2. Quadranten s3e2: CalcPoints 3, 2 mov ax, [anpunkt] s3e2a: mov bx, 394 call dritter xor ax, ax s3e2b: mov bx, 394 call vierter xor ax, ax jmp s1e2b ; Start im 3., Ende im 3. Quadranten s3e3: CalcPoints 3, 3 mov ax, [anpunkt] mov bx, [endpunkt] cmp ax, bx jle s3e33 mov bx, 394 call dritter xor ax, ax jmp s4e3a s3e33: jmp s1e3b ; Start im 3., Ende im 4. Quadranten s3e4: CalcPoints 3, 4 mov ax, [anpunkt] jmp s1e4b ; Start im 4., Ende im 1. Quadranten s4e1: CalcPoints 4, 1 mov ax, [anpunkt] jmp s2e1c ; Start im 4., Ende im 2. Quadranten s4e2: CalcPoints 4, 2 mov ax, [anpunkt] jmp s3e2b ; Start im 4., Ende im 3. Quadranten s4e3: CalcPoints 4, 3 mov ax, [anpunkt] s4e3a: mov bx, 394 call vierter xor ax, ax jmp s1e3c ; Start im 4., Ende im 4. Quadranten s4e4: CalcPoints 4, 4 mov ax, [anpunkt] mov bx, [endpunkt] cmp ax, bx jle s4e44 mov bx, 394 call vierter xor ax, ax jmp s1e4c s4e44: jmp s1e4d CircleExit1: pop di ; Alle Registerinhalte wieder pop si ; laden pop es pop dx pop cx pop bx pop ax ret ; Back home ENDP ; CURVE.ASM: Regelt die Parameterbernahme von Turbo Pascal aus fr ; die ASMCURVE-Routine in Turbo Assembler ; ; Autor: Frank Riemenschneider ; ; Eingabe: Parameter der CURVE-Funktion auf dem Stack ; Circle( XM, YM, XR, YR, AnfWinkel, EndWinkel:WORD ); ; Ausgabe: keine CODESEG PROC Curve FAR XMP:WORD, YMP:WORD, XRA:WORD, YRA:WORD, AnfWinkel:WORD, EndWinkel:WORD PUBLIC Curve mov ax, [XMP] ; Mittelpunkt-Koordinaten mov bx, [YMP] mov cx, [XRA] ; Radius in X- und Y-Richtung mov dx, [YRA] ; Koordinaten prfen cmp ax, 0 ; X-Koordinate < 0? jl CircleExit cmp ax, 239 ; X-Koordinate > 239? jg CircleExit cmp bx, 0 ; Y-Koordinate < 0? jl CircleExit cmp bx, 63 ; Y-Koordinate > 63? jg CircleExit mov si, [AnfWinkel] ; Anfangswinkel laden cmp si, 0 ; Anfangswinkel < 0ø? jl CircleExit cmp si, 359 ; Anfangswinkel > 359ø? jg CircleExit mov es, si mov si, [EndWinkel] ; Endwinkel laden cmp si, 0 ; Endwinkel < 0ø? jl CircleExit cmp si, 360 ; Endwinkel > 360ø? jg CircleExit call AsmCurve ; Curve-Routine aufrufen CircleExit: ret ; Back home ENDP