home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / assembler-kurs / lektionen / 68000d.txt next >
Text File  |  1977-12-31  |  27KB  |  654 lines

  1.  
  2. ; REFERENZTABELLE FÜR DIE 68000er PROGRAMMIERUNG
  3.  
  4. Synthetisch zusammengefaßt: Die Adressierungen:
  5.  
  6.  move.l #123,xxxx      ; Immediate: die Zahl 123 kommt sofort ins xxxx
  7.  move.l xxxx,$50000      ; Absolut long
  8.  move.l xxxx,$500.w      ; Absolut kurz (weniger als $7FFF)
  9.  move.l xxxx,D0          ; Datenregister direkt
  10.  move.l xxxx,A0          ; Adressregister direkt
  11.  move.l xxxx,(A0)      ; Datenregister indirekt
  12.  move.l xxxx,(A0)+      ; Adressregister indirekt mit Post-Inkrement
  13.  move.l xxxx,-(A0)      ; Adressregister indirekt mit Pre-Dekrement
  14.  move.l xxxx,$123(A0)      ; Adressregister indirekt mit Offset (Adressdistanz)
  15.  move.l xxxx,$12(a0,d0.w)    ; Adressregister indirekt mit Offset und Index
  16.  move.l Offset(PC),xxxx         ; Relativ zum PC mit Offset
  17.  move.l Offset(PC,d0.w),xxxx ; Relativ zum PC mit OFFSET
  18.  
  19.             -    -    -
  20.  
  21. *  Die  verschiedensten  Adressierungsarten  kann  man  in  Befehlen   mit
  22. Datenquelle und Datenziel "mischen", z.B. "move.l -(A0),12(a0,d3.l)".
  23.  
  24.             -    -    -
  25.  
  26. * Die Dezimalzahlen werden von keinem Symbol  angeführt  (z.B.  123),  die
  27. Hexadezimalzahlen  von  einem  $ (z.B. $1a0). Hexzahlen enthalten auch die
  28. Buchstaben von A bis F. Binärzahlen werden von  einem  %  angeführt,  z.B.
  29. %10010110,  sie bestehen nur aus 0 und 1 (Strom oder nicht im Draht!). Die
  30. Konvertierung  untereinander  der  drei   Zahlensysteme   bereitet   keine
  31. Probleme,  da  es unter dem ASMONE den "?"-Befehl gibt, gefolgt von der zu
  32. konvertierenden Zahl. Als Resultat erhält man das Äquivalente in  Dezimal,
  33. Hexadezimal  und  ASCII,  also  CHARAKTERN:  denn  auch die Buchstaben wie
  34. "ABCDabcde..." sind nur durch ein Byte dargestellt. So ist  z.B.  das  "Z"
  35. $5a   (Probiert   ?"z").  Um  Charakter  anzugeben  setzt  man  sie  unter
  36. Gänsefüßchen ("" oder ´´), und man kann sie mit den  Befehlen  kombinieren
  37. (z.B.  MOVE.B  #"a",Label1) oder mit dem DC.B direkt in den Speicher geben
  38. (DC.B "Ein Text im Speicher").
  39.  
  40.             -    -    -
  41.  
  42. * In Assembler wird die Multiplikation durch * dargestellt,  die  Division
  43. durch  /,  und  man  kann runde Klammern verwenden, wieviel man will, z.B:
  44. move.l #(100/2*(12+$41-32)+%01101010),RESULTAT
  45.  
  46. * 1 byte = 8 bit ($00 = %00000000; $FF = %11111111)
  47.   1 word = 16 bit ($0000 = %0000000000000000; $FFFF = %1111111111111111)
  48.   1 long = 32 bit, ossia 2 words ($00000000 = %000000000000000000000000000000)
  49.  
  50.             -    -    -
  51.  
  52. Bei Bits zählt man folgens: von 0 rechts nach links: z.B.  ein  Byte,  das
  53. Bit  5 auf 1 hat (oder High): $00100000. Bei einem Byte gehen die Bits von
  54. 0 (niederwertigsten) zum siebten (höchstwertigsten), ein Word  von  0  bis
  55. 15,  ein Longword von 0 bis 31. Um Bits leicht numerieren zu können, könnt
  56. ihr diesen Trick verwenden:
  57.  
  58.         ; 5432109876543210    - ein word
  59.     move.l  #%1000010000110000,d0   ; bit 15,10,5 e 4 High (auf 1)
  60.  
  61.             -    -    -
  62.  
  63. *Adressen werden per Konvention durch Hexzahlen dargestellt.
  64.  
  65.             -    -    -
  66.  
  67. *  Befehle  mit  dem "#"-Symbol, wie etwa MOVE.L #123,d0, CMP.L #10,LABEL1
  68. etc. betrachten die Zahl nach dem Lattenzaun (#) wie eine konstante  Zahl,
  69. also wirklich als "Nummer", nicht als Adresse, zum Unterschied wenn kein #
  70. vorhanden ist: move.b $12,$45 kopiert das Byte aus Adresse $12 in  Adresse
  71. $45, während move.b #$12,$45 die Zahl $12 in Adresse $45 kopiert.
  72.  
  73.             -    -    -
  74.  
  75. * Die DATENREGISTER und die ADRESSREGISTER sind alle 32 Bit lang, also ein
  76. Longword.  Auf Adressregistern kann man nur mit .W oder .L arbeiten, nicht
  77. mit .B.
  78.  
  79.             -    -    -
  80.  
  81. * Auf ungeraden Adressen kann  man  nicht  mit  .W  oder  .L-Instruktionen
  82. arbeiten,  nur  mit .B. Ein move.l #1,$10001 schickt den computer in GURU,
  83. während ein move.b #1,$10001 keine Probleme verursacht.
  84.  
  85.             -    -    -
  86.  
  87. *  Ein Byte kann eine Zahl zwischen $00 und $FF (255) enthalten, wenn dann
  88. noch etwas addiert wird, startet die Zahl wieder  bei  NULL.  Das  gleiche
  89. gilt  für  das  Word, bei dem $FFFF die größte, darstellbare Zahl ist, und
  90. für das Longword. Dies hat max. $FFFFFFFF.
  91.  
  92.             -    -    -
  93.  
  94. * Das LABEL,  die  KOMMENTARE  nach  den  ";"  und  die  DC.x  sind  keine
  95. 68000erBefehle,  aber  Assemblerbefehle, die es uns ermöglichen, Punkte im
  96. Listing (z.B. Daten oder Routinen) zu markieren, Kommentare einzufügen, um
  97. das  Listing klarer und verständlicher zu gestalten oder Bytes, Words oder
  98. Longwords direkt an einen bestimmten Punkt im Speicher  zu  geben  (DC.x).
  99. Das  kann  verifiziert  werden,  indem  man den Speicher mit dem Befehl "D
  100. $xxxx" oder "D LABEL" disassembliert.
  101.  
  102.  
  103. **  **  **  **  **  **  **  **  **  **  **  **  **  **  **  **
  104.  
  105. ; ADRESSIERUNGEN DES 68000 (Beispiele)
  106.  
  107. ; Adressierungen mit absoluten Adressen, .L (Longword)
  108.  
  109.  move.l #$123,$50000    ; wir geben $00000123 in $50000. Die Nullen links sind
  110.             ; Optional, denn move.l #$00000123,xxx unterscheidet
  111.             ; sich nicht von move.l #$123,xxx, im Speicher werden
  112.             ; die Nullen immer trotzdem angehängt.
  113.             ; ZU BEACHTEN ist, daß mit diesem .L-Befehl vier
  114.             ; Bytes im Speicher verändert werden, also die Bytes an
  115.             ; Adresse $50000, $50001, $50002 und $50003, die
  116.             ; folgende Werte erhalten:
  117.             ; $50000 = $00
  118.             ; $50001 = $00
  119.             ; $50002 = $01
  120.             ; $50003 = $23
  121.  
  122.             -    -    -
  123.  
  124. ; Adressierungen mit absoluten Adressen, .W (Word)
  125.  
  126.  move.w #$123,$50000    ; Wir geben $0123 in Adresse $50000 - Mit dieser
  127.             ; .W - Instruktion haben wir zwei Bytes verändert,
  128.             ; da ein Word 2 Bytes lang ist, und zwar die
  129.             ; Adressen $50000 und $50001:
  130.             ; $50000 = $01
  131.             ; $50001 = $23
  132.  
  133.             -    -    -
  134.  
  135. ; Adressierungen mit absoluten Adressen, .B (Byte)
  136.  
  137.  move.B #$12,$50000    ; Wir geben $12 in Adresse $50000. Mit diesem .b-Befehl
  138.             ; haben wir 1 Byte modifiziert, und zwar das an
  139.             ; Adresse $50000 = $12.
  140.             ; PASST GUT AUF DIE UNTERSCHIEDE AUF, DIE EINTRETEN,
  141.             ; WENN IHR EINFACH .L, .W UND .B VERTAUSCHT. In der Tat
  142.             ; liegen oft Fehler der Anfänger darin, diese drei
  143.             ; Typen zu vertauschen oder ihrer falschen Einschätzung
  144.             ; Verwendet den Debugger ("AD"), dann die > Taste um
  145.             ; auch die letztn Zweifel auszuschalten.
  146.  
  147.  move.l $40000,$50000    ; In diesem Fall geben wir den Inhalt aus Byte
  148.             ; $40000, $40001, $40002 und $40003 in die vier
  149.             ; Bytes ab $50000, also in das Byte $50000, $50001,
  150.             ; $50003 und $50004. Wenn z.B. $40000 = 00102305 war:
  151.             ; $50000 = $00
  152.             ; $50001 = $10
  153.             ; $50002 = $23
  154.             ; $50003 = $04
  155.             ; Auf die gleiche Weise kopieren wir mit einem
  156.             ; .W oder .B von einer Adresse zu anderen jeweils
  157.             ; zwei Bytes oder eines.
  158.  
  159.             -    -    -
  160.                               
  161. BEMERKUNG: Wenn wir LABEL verwenden, um Daten im  Speicher  zu  verändern,
  162. werden  sie  vom Assembler in die EFFEKTIVEN ADRESSEN umgewandelt, die sie
  163. darstellen. Da Label ja Punkte im Speicher markieren, wie  Etiketten  oder
  164. Schildchen,  werden wir uns auf genau diesen Punkt beziehen, wenn wir eine
  165. in irgend einer Art ansprechen oder aufrufen. Befehle  wie  die  folgenden
  166. sind dann auch bei der absoluten Adressierung mit beinhaltet:
  167.  
  168.     MOVE.L    LABEL1,$50000
  169.     MOVE.W    #$123,LABELBLAU
  170.     MOVE.B    LABELHUND,LABELKATZE
  171.  
  172. Diese werden im Speicher dann immer in ähnlicher Weise dastehen:
  173.  
  174.     MOVE.L    $64230,$50000    ; angenommen LABEL1 sei auf $64230
  175.     MOVE.W    #$123,$726e0    ; angenommen LABEL1 sei auf $726e0
  176.     MOVE.B    $23450,$3a010    ; wie oben...
  177.  
  178. Also, mit Bytes, Words oder Longwords, die mit Labels gekennzeichnet sind,
  179. müßt  ihr umgehen, als seien es Adressen, den, einmal ASSEMBLIERT, SIND ES
  180. ADRESSEN!!!
  181.  
  182. Deswegen wird bei folgendem Befehl
  183.  
  184.     MOVE.L    #LABEL1,$dff080    ; Verwendet, um unsere Copperlist
  185.                 ; "anzupeilen"
  186.  
  187. in $dff080 die Adresse von LABEL1 gegeben, und nicht die vier  Bytes,  die
  188. ab  LABEL1  stehen:  weil  LABEL1  in ihre äquivalente Adresse konvertiert
  189. wird, und da es nach einem # steht, wird diese Adresse  als  ("konstante")
  190. Zahl  betrachtet, und somit wird diese Zahl in $dff080 kopiert. Machen wir
  191. ein Beispiel:
  192.  
  193.     MOVE.L    #LABEL1,LABEL2
  194.     MOVE.L    LABEL1,LABEL2
  195.  
  196. Werden  so  assembliert:  (Für  das  Label  werden  hypotetische  Adressen
  197. angenommen)
  198.  
  199.     MOVE.L    #$42300,$53120    ; In $53120 kommt die Zahl $42300,
  200.                 ; also die Adresse des Label
  201.     MOVE.L    $42300,$53120    ; In $53120 wird das Longword kopiert,
  202.                 ; das sich ab Adresse $42300 befindet
  203.  
  204.  
  205.             -    -    -
  206.                               
  207. Es ist möglich,  sich  auf  elegantere  Weise  auf  absolute  Adressen  zu
  208. beziehen, wenn sie kleiner als das Word sind, also $7FFF, indem man ein .W
  209. nach der Adresse anhängt: das ist z.B. der Fall bei Move.L 4.w,A6, das die
  210. ExecBase  in  A6  ladet,  aber  jede Instruktion, die mit Adressen mit der
  211. Länge des Word operieren, können so abgekürzt werden.  Die  Ersparnis  der
  212. linken  vier  Nullen wirkt sich Geschwindigkeitssteigernd aus. Schauen wir
  213. uns den Unterschied an:
  214.  
  215.                 (assembliert)
  216.     MOVE.B    #10,$123    -> MOVE.B #10,$00000123
  217.     MOVE.B    #10,$123.w    -> MOVE.B #10,$0123    -OHNE ÜBERFLÜSSIGEN
  218.                              NULLEN
  219.  
  220. Der Effekt des Befehles ÄNDERT SICH NICHT! Es ändert sich nur die  "Form",
  221. die  schlanker  und  schneller erscheint. Wenn man vergißt, das .w bei den
  222. "kurzen" Befehlen anzuhängen, dann produziert man  nur  Code,  der  einige
  223. Word länger ist, nicht mehr.
  224.  
  225. **    **    **    **    **    **    **    **    **    **    **
  226.  
  227. ; Datenregister, .L (Longword)
  228.  
  229.  move.l #$123,d0    ; Datenregister direkt (wir geben $123 in D0)
  230.  
  231.  move.l d1,d0        ; Datenregister direkt, wir geben den Wert, der in
  232.             ; d1 enthalten ist, in d0)
  233.  
  234. ; Datenregister, .W (Word)    (Bemerkung: Man nennt die rechte Hälfte des
  235.                 Long das "niederwertige Word", die linke
  236.                 das "höherwertige Word": $HOCH+NIEDER, 
  237.                 .L = 4 Byte = 2 Word)
  238.  
  239.  move.w #$123,d0    ; In diesem Fall haben wir nur das niederwertige
  240.             ; Word von d0 verändert: wenn d0 $0012fe3c war, und
  241.             ; wir nur auf dem niederwertigen Word agieren, also
  242.             ; $fe3c, dann wird d0 danach so aussehen: $00120123
  243.  
  244.  move.w d1,d0        ; Das Gleiche, wir kopieren das niederwertige Word
  245.             ; von d1 ins niederwertige Word von d0. Wenn d1
  246.             ; $12345678 enthält, und d0 $9abcdef0, dann wird nach
  247.             ; diesem Befehl d0 folgendes enthalten: $9abc5678
  248.                                      ^^^^ WORD!
  249.  
  250. ; Datenregister, .B (Byte)
  251.  
  252.  move.b #$12,d0        ; In diesem Fall ändern wir nur das Byte ganz rechts,
  253.             ; wenn d0 z.B. $0012fe3c war, nur auf dem ersten
  254.             ; Byte zugreifend, wird es so verändert: d0=$0012fe12
  255.  
  256.  move.b d1,d0        ; Das Gleiche, wir kopieren das erste Byte von d1
  257.             ; in das erste Byte von d0. Wenn d1 $12345678 enthält,
  258.             ; während d0 $9abcdef0, dann wird nach dieser Instr.
  259.             ; d0 so aussehen: $9abcde78
  260.                          ^^ Byte!
  261.  
  262. Die  Adressregister  a0,a1,a2,a3,a4,a5 und a6 (VERWENDET NICHT A7, auch SP
  263. genannt - Stack Pointer) verhalten sich wie die  Datenregister,  nur  kann
  264. man  auf  ihnen  NICHT  mit .B zugreifen. Man kann darin auch Daten geben,
  265. auch wenn sie für Adressen vorgesehen sind.
  266.  
  267.  
  268. **    **    **    **    **    **    **    **    **    **    **
  269.   
  270. ; INDIREKTE ADRESSIERUNGEN MITTELS ADRESSREGISTERN
  271.  
  272.  move.w #123,(a0)    ; Bei diesem Move wird die Zahl 123 in das Word
  273.             ; kopiert, das sich ab der Adresse befindet, die
  274.             ; in a0 steht. Man sagt indirekt dazu, weil die
  275.             ; Zieladresse nicht direkt angegeben ist, sondern
  276.             ; Mittels Register, das die Adresse enthält. Das
  277.             ; geschieht nur, wenn das Adressregister in Klammern
  278.             ; geschrieben steht, ansonsten würde man 123 in das
  279.             ; Register selbst schreiben. Ein DATENREGISTER kann
  280.             ; NICHT dazu verwendet werden, eine indirekte
  281.             ; Adressierung zu verrichten.
  282.             ; Man kann sagen, daß das Ragister a0 als ZEIGER
  283.             ; auf eine Speicherzelle verwendet wurde, es ZEIGT
  284.             ; also wie der Mauspointer oder ein Spürhund in
  285.             ; Richtung der Beute: man nennt eine Adresse oder
  286.             ; ein Register "ZEIGER", wenn dessen Inhalt eine Adres.
  287.             ; von irgend etwas enthält,auf das man zugreift,
  288.             ; indem man den Zeiger fragt, wo sich dieses befindet.
  289.             ; Zeiger werden meist auch als "POINTER" bezeichnet.
  290.             ; Z.B. die Copperlist hat ein Pointerregister, das
  291.             ; $dff080, in das die Adresse der Copperlist gegeben
  292.             ; wird. Der Copper schaut bei jedem Fotogramm in
  293.             ; $dff080 nach, wo sich die Copperlist befindet.
  294.  
  295.  move.l (a0),(a1)    ; In diesem Fall wird das Long, das sich ab Adresse a0
  296.             ; befindet, in Adresse a1 kopiert. Wenn vor der
  297.             ; Ausführung dieses Befehles in a0 die Adresse $100
  298.             ; gestanden hätte, und in a1 $200, dann wäre dieser
  299.             ; gleichwertig mit einem
  300.             ; MOVE.L $100,$200, oder, noch raffinierter, 
  301.             ; MOVE.L $100.w,$200.w...
  302.  
  303.             -    -    -
  304.   
  305. ; INDIREKTE ADRESSIERUNG MIT POST-INKREMENTIERUNG (Erhöhung der Adresse NACH
  306.                             Ausführung)
  307.  
  308.  move.w #123,(a0)+    ; Auf diese Art wird die Zahl 123 in das Word kopiert,
  309.             ; das sich ab Adresse a0 befindet, und DANACH wird
  310.             ; a0 um ein WORD INKREMENTIERT. Wenn die Anweisung ein
  311.             ; .B gewesen wäre, dann würde nach dem Move a0 um nur
  312.             ; ein Byte erhöht, bei einem .L um 4 Bytes, also ein
  313.             ; Long.
  314.  
  315.  move.l (a0)+,(a1)+    ; Mit dieser Anordnung kopieren wir das Long, das sich
  316.             ; ab Adresse a0 befindet, in Adresse a1 und folgende,
  317.             ; und danach werden beide Register, a0 und a1, um
  318.             ; jeweils vier Byte erhöht (Long).
  319.             ; Praktisch bewegen wir uns auf die darauffolgenden
  320.             ; Longword im Speicher. Mit einer Serie solcher
  321.             ; Instruktionen könnte man ein Stück Speicher kopieren:
  322.  
  323.     lea    $50000,a0    ; Quell-Adressee
  324.     lea    $60000,a1    ; Ziel-Adresse
  325.     move.l  (a0)+,(a1)+
  326.     move.l  (a0)+,(a1)+
  327.     move.l  (a0)+,(a1)+
  328.     move.l  (a0)+,(a1)+
  329.     move.l  (a0)+,(a1)+
  330.                 ; Jetzt haben wir 5 Longwords von $50000 nach
  331.                 ; $60000 kopiert.
  332.  
  333.             -    -    -
  334.             
  335. ; INDIREKTE ADRESSIERUNG MIT PRE-DEKREMENT (Adresse wird VOR Ausführung
  336.                          erniedrigt)
  337.  
  338.  move.w #123,-(a0)    ; ALS ERSTES WIRD A0 UM 2 BYTES DEKREMENTIERT
  339.             ; (verringert, abgezogen), ALSO UM EIN WORD,
  340.             ; und DANACH wird 123 in das Word kopiert, das 
  341.             ; sich ab der Adresse, die in a0 steht, befindet.
  342.             ; Wenn die Anweisung eine .B gewesen wäre, dann
  343.             ; würde dem a0 nur 1 Byte abgezogen, bei einem
  344.             ; .L hingegen 4 Byte (Long).
  345.  
  346.  move.l -(a0),-(a1)    ; a0 und a1 werden beide um jeweils 4 Bytes
  347.             ; dekrementiert (Long), und dann wird der Inhalt,
  348.             ; der sich ab der nun resultierenden Adresse a0
  349.             ; befindet, in die jetzt resultierende Adresse a1
  350.             ; kopiert.
  351.  
  352.         ; Mit einer Reihe solcher Befehle könnte man, wie im vorigen
  353.         ; Fall, ein Stück Speicher kopieren, aber mit dem
  354.         ; Unterschied, daß man rückwärts vorgehen würde, so
  355.         ; wie Krebse. Wir müßten bei der Adresse starten, die
  356.         ; das Ende der Kopie ist, und nach hinten gehen, bis
  357.         ; wir den Anfang erreicht haben, im Beispiel $50000 und
  358.         ; $60000. Setzten wir also $50014 und $60014 als Startwert,
  359.         ; und dann kopieren wir solange ein Long "nach hinten", bis
  360.         ; wir bei $50000 bzw. $60000 angekommen sind: um die Adresse
  361.         ; zu berechnen, bei der wir starten müssen, habe ich zum
  362.         ; Anfangswert (5*4) dazugezählt, also = $14, praktisch
  363.         ; 5 Longwords * 4 Bytes pro Long. Zu Beachten, daß im Speicher
  364.         ; $50000+(5*4) als $50014 assembliert wird, denn während der
  365.         ; Assemblierfase werden auch eventuelle mathematische
  366.         ; Operationen durchgeführt.
  367.  
  368.     lea    $50000+(5*4),a0    ; Quelladresse am ENDE
  369.     lea    $60000+(5*4),a1    ; Zieladresse am ENDE
  370.     move.l  -(a0),-(a1)
  371.     move.l  -(a0),-(a1)
  372.     move.l  -(a0),-(a1)
  373.     move.l  -(a0),-(a1)
  374.     move.l  -(a0),-(a1)
  375.  
  376.         ; In diesem Fall haben wir 5 Longwords von $50000
  377.         ; nach $60000 kopiert, aber sind bei $50014 gestartet
  378.         ; und bis $50000 nach "hinten" gegangen. Der Unter-
  379.         ; schied zum vorigen Beispiel ist wie der Unterschied,
  380.         ; der darin besteht, den Flur von Links oder von
  381.         ; Rechts her zu putzen: in beiden Fällen "kopieren" wir
  382.         ; den Schmutz in den Eimer, aber in zwei verschiedenen
  383.         ; Richtungen.
  384.  
  385.             -    -    -
  386.     
  387. ; INDIREKTE ADRESSIERUNG MIT ADRESSIERUNGSDISTANZ (OFFSET) UND INDEX
  388.  
  389.  move.w #12,5(a0,d0.w)  ; Bei dieser Anweisung wird 12 in das Word kopiert,
  390.             ; das sich ab der Adresse befindet, die sich aus
  391.             ; der Summe von 5 + a0 + Word in d0 bildet. Wenn z.B.
  392.             ; in a0 $50000 stehen würde, und in d0 $1000, dann
  393.             ; würde 12 auf die Adresse $51005 kopiert.
  394.             ; Das Offset kann hier aber nur zwischen -128 und +127
  395.             ; variieren.
  396.             ; Praktisch wird zur Summe, die die Adresse ergibt,
  397.             ; auch noch ein Register hinzugezogen,das sowohl
  398.             ; DATEN- wie auch ADRESSREGISTER sein kann, bei dem
  399.             ; der ganze Inhalt verwendet werden kann (.L) wie auch
  400.             ; nur ein Word (.W).
  401.             ; Byteweise ist es nicht verwendbar. Man nennt dieses
  402.             ; zusätzliche Register INDEX.
  403.  
  404.           EINIGE BEISPIELE:
  405.     
  406.     lea    $50000,a3
  407.     move.w  #$6000,d2
  408.     move.l  #123,$30(a3,d2.w)    ; kopiert 123 in $56030
  409. *
  410.     lea    $33000,a1
  411.     move.w  #$2000,a2
  412.     move.l  #123,$10(a1,a2.w)    ; kopiert 123 in $35010
  413. *
  414.     lea    $33000,a1
  415.     lea    $20010,a2
  416.     move.l  #123,-$10(a1,a2.l)    ; kopiert 123 in $53000
  417.  
  418. **    **    **    **    **    **    **    **    **    **    **
  419.   
  420. ; ADRESSIERUNGEN RELATIV ZUM PC (mit automatischem Offset)
  421.  
  422. Diese Art der Adressierungen werden  vom  ASMONE  automatisch  in  Ordnung
  423. gebracht,   sie   werden   unbemerkt  übergangen:  z.B.  schaut  euch  den
  424. Unterschied zwischen diesen beiden Anweisungen an:
  425.  
  426.     MOVE.L  LABEL1,d0        ; ABSOLUTE ADRESSE
  427.     MOVE.L  LABEL1(PC),d0        ; ADRESSE RELATIV ZUM PC
  428.  
  429. Diese beiden Anweisungen tun das Geliche, aber die mit dem (PC) ist kürzer
  430. und  schneller als die Erste. Sie ist relativ zum PC, denn die basiert auf
  431. einer Adressierungs-Distanz (Offset) in Bezug  auf  das  PC-Register,  dem
  432. PROGRAM  COUNTER, das ist das Register, in dem der 68000 Buch führt, wo er
  433. gerade mit der Ausführung ist. Das Offset wird automatisch  von  Assembler
  434. errechnet,  und  im Speicher landet dann gleich schon das richtige Offset,
  435. um sich zwischen den Label und anderen Anweisungen richtig zu orientieren.
  436. Die  Instruktion enthält nun nicht mehr die Adresse der Label, sondern die
  437. Anzahl der Bytes, die die Entfernung davon nach vorne/hinten angeben.  Der
  438. Unterschied   ist   klar:   wenn  wir  den  ganzen  Code  in  eine  andere
  439. Speicherregion verlegen, dann verschieben sich die absoluten Adressen, die
  440. Distanzen  zwischen  den  Labels  und den (PC)-Befehlen aber bleibt gleich
  441. groß, deswegen "funktioniert" diese Methode immer, während ein  nicht  zum
  442. PC-relatives  Programm,  wenn  an  einen anderen Ort im Speicher versetzt,
  443. alles in Chaos stürzt. Denn ein move.l  LABEL1,d0  wird  als  (angenommen)
  444. MOVE.L  $23000,d0  übersetzt,  also  befindet  sich  das Label auf Adresse
  445. $23000. Wenn wir nun das ganze Programm, das z.B. bei $20000 startete  und
  446. bei  $25000  endete, um $10000 nach vorne verschieben, dann werden bei der
  447. Ausführung  nicht  indifferente  Fehler  auftreten,  da  sich  ein  MOVE.L
  448. $23000,d0  nicht  mehr  auf LABEL1 bezieht, das liegt jetzt ja auf $33000!
  449. Aber wenn der Code vollständig relativ zum PC erstellt wurde,  dann  hätte
  450. sich  das  MOVE  immer auf das Label bezogen, also auf $33000, da es die -
  451. immer gleichbelibende -Distanz zum Label berechnet hätte. Auch Befehle wie
  452. BRA,  BSR,  BNE,  BEQ  sind  relativ  zum  PC,  ein BSR.W ROUTINE1 wird im
  453. Speicher z.B. als BSR (50 Bytes weiter vorne) assembliert, und  nicht  BSR
  454. $30000.  Adressen  werden von Befehlen assembliert, die äquivalent zum BSR
  455. sind, wie etwa JSR: ein  JSR  LABEL1  wird  mit  der  Adresse  von  Label1
  456. assembliert,  genauso  ein wird JMP (SPRINGE-Äquivalent zum BRA) die REALE
  457. ADRESSE von LABLE1 bekommen. Aber wieso  wird  nicht  immer  einfach  eine
  458. Adressierung  relativ  zum PC vorgezogen, also ein BSR einem JSR? Weil die
  459. Adressierungen mit PC das Limit haben, sich nur auf Adressen  beziehen  zu
  460. können,  die  maximal 32767 Bytes nach vorne oder -32768 Bytes nach hinten
  461. liegen. Für weiter entfernte Label müssen Move mit absoluter Adresse  oder
  462. JSR/JMP  eingesetzt  werden.  Aber,  wie  schon  gesagt,  werden all diese
  463. Rechenaufgaben vom Assembler übernommen, deswegen  interessieren  sie  uns
  464. nicht,  wir müssen  uns  nur  erinnern,  DAß  WENN MÖGLICH, IMMER ein (PC)
  465. gesetzt werden sollte, und BSR und BRA an Stelle von JSR und JMP verwendet
  466. werden sollten. Sollte die Distanz zu groß sein, dann meldet der Assembler
  467. einen Fehler, und wir müssen das (PC) entfernen oder schlimmstenfalls  das
  468. BRA/BSR  durch  JMP/JSR  ersetzen,  das die größten Entfernungen erreichen
  469. kann. Man könnte auch nur mit JMP/JSR und ohne  (PC)  programmieren,  aber
  470. der  Code  würde  länger  und  um  einen  Augenblick langsamer erscheinen,
  471. deswegen ist immer besser, alles so  gut  als  möglich  zu  machen!!!  Das
  472. Problem  der  RELOCATION,  also  des  Verschiebens  im  Speicher, wird vom
  473. Betriebssystem übernommen: wenn wir unser Programm mit WO als Ausführbares
  474. abspeichern,  dann  speichern  wir  ein  File  ab,  das  von der Shell aus
  475. aufgerufen werden kann, indem man seinen Namen eingibt. Das Betriebssystem
  476. kümmert  sich  dann  darum, es an einen freien Platz im Speicher zu geben,
  477. der irgendwo sein kann, und reallociert (A.d.Ü: tut mir  leid,  mir  fällt
  478. für  ALLOCATE kein deutsches Wort ein. Es bedeutet soviel wie "ansiedeln",
  479. "zuteilen",  "anweisen".  Wer  einen  Deutsche   Ausdruck   kennt,   bitte
  480. "Readme.Deutsch"  lesen!) das Programm, es passt also die Adressen der JSR
  481. und der nicht zum PC relativen Move an, um den neuen Gegebenheiten (andere
  482. Adressen)  zu  entprechen. Deswegen kann man auch programmieren, ohne sich
  483. den Kopf darüber zu zerbrechen, überall die (PC) für Labels zu setzen, die
  484. sich  in  anderen  SECTIONS befinden: z.B. die COPPERLIST befindet sich in
  485. einer anderen SECTION, und sie kann nur geändert  werden,  wenn  man  ohne
  486. (PC)  arbeitet,  weil das Betriebssystem die Sektionen auf unvorhersehbare
  487. Distanzen setzt (allocate...), die vielleicht sogar größer sind als 32768,
  488. also dem LIMIT der RC-Realtiven Adressierung.
  489.  
  490.  
  491.     BEISPIELE FÜR PC-RELATIVE ADRESSIERUNGEN:
  492.  
  493.     MOVE.L  LABEL1(PC),LABEL2    ; Bemerkung: man kann das (PC) nicht
  494.                     ; für Labels verwenden, die als Ziel
  495.                     ; stehen!
  496.                     ; move.l a0,LABEL(PC) ist ein Fehler!
  497.     ADD.L    LABELBAU(PC),d0        ; Geht weil das Label die QUELLE ist
  498.     SUB.L    #500,LABEL        ; KEIN PC, WEIL HIER DAS LABEL
  499.                     ; EIN ZIEL IST
  500.     CLR.L    LABEL            ; hier kann kein PC gesetzt werden.
  501.                     ; Praktisch kann man ein (PC) nur
  502.                     ; einsetzen, wenn es vor einem
  503.                     ; Beistrich steht!
  504.  
  505. ; ADRESSIERUNGEN RELATIV ZUM PC MIT OFFSET UND INDEX
  506.  
  507. Diese Adressierung ist das Gleiche wie vorhin, nur mit INDEX,  also  einem
  508. Register,  das  zum (PC) und zum Offset summiert wird, genauso wie es beim
  509. Offset+Index mit Adressregistern geschieht:
  510.  
  511.     MOVE.L    LABEL1(PC,d0.w),LABEL2  ; Wie die PC-Adressierung, nur muß
  512.                     ; noch das Word in d0 dazugezählt
  513.                     ; werden, wir beziehen uns also nicht
  514.                     ; auf LABEL1, sondern auf ein Label,
  515.                     ; das d0 von LABEL1 entfernt ist.
  516.     ADD.L    LABELWAU(PC,a0.l),d0    ; Wie vorher, a0.l wird als Index
  517.                     ; verwendet.
  518.  
  519. Das ist alles, was die Adressierungen angeht.
  520.  
  521. **    **    **    **    **    **    **    **    **    **    **
  522.   
  523. GEBRÄUCHLICHSTEN BEFEHLE:
  524.  
  525.     MOVE.x    QUELLE,ZIEL    ; Kopiert ein Byte, ein Word oder
  526.                 ; ein Longword
  527.  
  528.     LEA    Adresse,Ax    ; Ladet eine Adresse: Diese Anweisung
  529.                 ; kann nur mit Adressregistern verwendet
  530.                 ; werden. Sie dient dazu, die entsprechende
  531.                 ; Adresse (sei sie nun in Form eines Label
  532.                 ; oder einer Zahl gegeben, z.B. $50000)
  533.                 ; ins Register zu geben.
  534.                 ; Das gleiche wie : MOVE.L #Adresse,a0
  535.                 ; aber schneller!
  536.  
  537.     CLR.x    Ziel        ; Dieser Befehl löscht das Ziel 
  538.                 ; (setzt es auf 0) CLR = CLEAR = "REINIGE"
  539.  
  540. BEDINGTE SPRÜNGE MIT EINEM TST, BTST, CMP
  541.  
  542.     CMP.x    Quelle, Ziel    ; Vergleicht zwei Operanden, die ein
  543.                 ; Label oder ein Register sein können, oder
  544.                 ; sonst eine absolute Zahl (#)  mit einem
  545.                 ; Register uvm. POITIVES Ergebnis, wenn die
  546.                 ; zwei Operanden GLEICH sind (für folgende
  547.                 ; BEQ/BNE)
  548.  
  549.     TST.x    Register.Label/Adresse  ; Kontrolliert, ob der fragliche
  550.                     ; Operand gleich NULL ist, wenn ja,
  551.                     ; Positives Ergebnis
  552.  
  553.     BTST    #x,Adresse/Dx    ; Kontrolliert, ob Bit x der Adresse
  554.                 ; auf NULL steht; wenn ja POSITIVES
  555.                 ; Ergebnis. Man kann ein BTST auch auf
  556.                 ; ein Datenregister ausführen, in diesem
  557.                 ; Fall ist ein Test auf einem der 32 möglichen
  558.                 ; Bits (0-31) erlaubt. Wird das BTST auf eine
  559.                 ; Speicherzelle angewandt, so muß man sich mit
  560.                 ; einem Byte (0-7) begnügen.
  561.  
  562. Sofort nach dem CMP, TST oder BTST steht immer ein BNE, ein BEQ  oder  ein
  563. anderer,  ähnlicher  Befehl.  Im  Falle  des  BNE  oder  des  BEQ kann man
  564. Verzweigungen oder konditionierte Sprünge  vom  TST/CMP  aus  machen.  DIE
  565. BEW/BNE/BSR/BRA können sowohl .w wie auch .b sein, jenachdem, wie weit die
  566. Routine vom Aufrufenden Befehl entfernt ist. Wenn sie  sehr  nahe  liegen,
  567. kann auch ein .b verwendet werden, das oft als .s geschrieben wird. Es ist
  568. das Gleiche (s= SHORT, -> KURZ).
  569.  
  570.     BSR.x    label        ; Führe die Routine LABEL aus, und wenn
  571.                 ; du auf ein RTS am Ende der Routine stößt,
  572.                 ; dann kehre zurück.
  573.  
  574.     BEQ.x    label        ; Wenn das Resultat der vorherigen Abfrage
  575.                 ; POSITIV war, dann springe zum Label
  576.                 ; (DANACH ABER KEHRE NICHT ZURÜCK, WIE IM
  577.                 ; FALLE DES BSR, HIER WIRD GEWÄHLT ZWISCHEN
  578.                 ; SPRINGEN ODER NICHT
  579.  
  580.     BNE.x    label        ; Wenn das Resultat NICHT positiv war,
  581.                 ; dann springe zum Label
  582.                 ; (DANACH ABER KEHRE NICHT ZURÜCK, WIE IM
  583.                 ; FALLE DES BSR, HIER WIRD GEWÄHLT ZWISCHEN
  584.                 ; SPRINGEN ODER NICHT
  585.   
  586.     BRA.x    label        ; Springe IMMER zum Label (wie JMP)
  587.  
  588.     ADD.x    Operand1,Ziel    ; Mit diesem Befehl wird ein Wert zum
  589.                 ; Ziel addiert
  590.  
  591.     SUB.x    Operand1,Ziel    ; Mit diesem Befehl wird ein Wert
  592.                 ; von Ziel subtrahiert
  593.  
  594.     SWAP    Dx        ; Vertauscht die 2 Words des Longwords
  595.                 ; in einem DATENREGISTER, braucht kein
  596.                 ; .B, .W oder .L
  597.  
  598. SWAP  kommt aus dem Englichen (Wunder, Wunder), und bedeutet "Vertausche",
  599. in der Tat vertauscht es die zwei Words, aus dem ein Longword besteht:
  600.  
  601.     MOVE.L    #HUNDMAUS,d0    ; in d0 kommt das Longword HUNDMAUS
  602.  
  603.     SWAP    d0        ; Wir vertauschen die Words: in d0
  604.                 ; steht jetzt MAUSHUND !!!!
  605.  
  606.                 *
  607.  
  608. Bemerkung: Es existieren Anweisungen,  die  den  Adressregistern  gewidmet
  609. sind: z.B. müssen wir CMPA.W d0,a0 schreiben und nicht CMP.W d0,a0,auf die
  610. gleiche Art und Weise ADDA.W a2,a0 und nicht ADD.W a2,a0.  Für  Konstanten
  611. hingegen  (#xxxx)  müssen wir  CMPI.x  #10,d0  verwenden,  und nicht CMP.x
  612. #10,d0. Genauso SUBI.x #123,d2 und nicht SUB.x #123,d2,  aber  der  ASMONE
  613. assembliert  immer  AUTOMATISCH  die richtige Anweisung, auch wenn wir nur
  614. cmp/add/sub schreiben. Also, keine Sorgen, wenn in  einem  Listing  einmal
  615. CMPI auftaucht, weiter unten dann CMP alleine, oder adda und add, weil der
  616. ASMONE immer alles zum Rechten biegt. Zum Testen assembliert die folgenden
  617. Zeilen  und  disassembliert mit "D PROBE", der ASMONE wird nach den Regeln
  618. assemblieren.
  619.  
  620. PROBE:
  621.     CMP.W    d0,a0
  622.     ADD.W    a1,a2
  623.     SUB.L    #123,$10000
  624.     CMP.b    #20,d4
  625.  
  626. Wird so assembliert werden:
  627.  
  628.     CMPA.W    D0,A0
  629.     ADDA.W    A1,A2
  630.     SUBI.L    #$0000007B,$00010000
  631.     CMPI.B    #$14,D4
  632.  
  633.  
  634.             -    -    -
  635.       
  636. Bemerkung2:  Gewisse  Instruktionen,  die  das  gleiche  tun,  können  auf
  637. verschiedene  Weise  geschrieben werden: z.B. hat der 68000er Befehle, die
  638. bestimmten Situationen angepasst sind, und dort schneller sind:
  639.  
  640. 1)    ADDQ.x    #Zahl,Ziel    ; Der Befehl ADDQ.x kann für Additionen
  641.                 ; verwendet werden, dessen Zahlen kleiner
  642.                 ; sind als 8 (Q = Quick, "Schnell")
  643.  
  644. 2)    SUBQ.x    #Zahl,Ziel    ; Der Befehl SUBQ.x kann für Subtraktionen
  645.                 ; mit Zahlen von 1 bis 8 verwendet werde,
  646.                 ; (wie oben...)
  647.  
  648. 3)    MOVEQ    #Zahl,dx    ; Das MOVEQ kann dazu verwendet werden, um
  649.                 ; das MOVE.L #Zahl,d0 zu ersetzen, wobei
  650.                 ; Zahl zwischen -128 und +127 liegen muß.
  651.                 ; Das MoveQ ist immer .L, deswegen braucht
  652.                 ; es kein .B, .W oder .L.
  653.  
  654.