[8051] Assambler - Flags
-
Hallo!
In der Schule lernen wie gerade Assambler Mikrocontroller 8051 zu programmieren, aber derzeit nur auf den Zettel...
Bsp:
MOV A,#100dez ADD A,#40dez
Aufgabenstellung: Ermittle den Inhalt des Akkus und der Flags(AC, C, OV) nach ADD.
Naja die 100 wird in den A geschrieben und dann wird eben 40 zu 100 drauf gehählt --> im Akku steht am ende 140dez.
Aber wie ermittelt man die Flags, wie Auxilliare Carry Flag, Carry Flag und Overflow Flag?
Ich hab die flags gegoogelt, aber weis einfach nicht genau was die können etc. :(.
Kann mir das einer bitte erklären?
mfg gast
-
Eine gute Hilfe für solche Sachen ist übrigens das Windows/Dos Programm debug.
Hm, und Internet...
google "carryflag wiki" und soEs ist aber gut, wenn man binärrechnen kann, die Regeln sind einfach:
0+0=0
1+0 oder 0+1 = 1
1+1=10
1+1+1 = 11wieviel ist also
11 + 1
oder 11 * 11?in Debug:
müsste man einmal AX mit FFFF laden bx mit 1 laden und mit add zusammenzählen und gucken was die Flags anzeigen, und danach AX nochmal mit FFFF laden und auch BX mit FFFF laden und beide multiplizieren über AX mit dem Befehl "mul BX" und gucken, was die Flags anzeigen.C:\Users\nachtfeuer>debug
-a ;a wie assembly, debugs asm editor 1A05:0100 mov ax,ffff 1A05:0103 mov bx,1 1A05:0106 add ax,bx 1A05:0108 mov ax,ffff 1A05:010B mov bx,ffff 1A05:010E mul bx 1A05:0110 -t ;jetzt testen und Flags angucken mit "t" AX=FFFF BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=0103 NV UP EI NG NZ NA PE NC 1A05:0103 BB0100 MOV BX,0001 -t AX=FFFF BX=0001 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=0106 NV UP EI PL NZ NA PO NC 1A05:0106 01D8 ADD AX,BX -t AX=0000 BX=0001 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=0108 NV UP EI PL ZR AC PE CY 1A05:0108 B8FFFF MOV AX,FFFF -t AX=FFFF BX=0001 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=010B NV UP EI PL ZR AC PE CY 1A05:010B BBFFFF MOV BX,FFFF -t AX=FFFF BX=FFFF CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=010E NV UP EI PL ZR AC PE CY 1A05:010E F7E3 MUL BX -t AX=0001 BX=FFFF CX=0000 DX=FFFE SP=FFEE BP=0000 SI=0000 DI=0000 DS=1A05 ES=1A05 SS=1A05 CS=1A05 IP=0110 OV UP EI PL ZR AC PE CY 1A05:0110 0000 ADD [BX+SI],AL DS:FFFF=00
-
Die Flags zeigen an, dass bei der letzten Operation etwas Bestimmtes passiert ist. C, AC und OV teilen mit, dass beim ADD irgendwo ein Übertrag aufgetaucht ist.
Beispiel:
138 + 75 = 213
Und nun grundschulmäßig auf Papier:
Augend 138 Addend 75 Übertrag 11 ============== Ergebnis 213
Für den Mikrocontroller machst Du dasselbe, aber binar:
Augend 10001010 Addend 01001011 Übertrag 1 1 =================== Ergebnis 11010101
Wenn Du die einzelnen Bits von rechts nach links mit 0 bis 7 durchnummerierst, dann siehst Du, dass bei Bit1 (1+1=10 -> 0, Übertrag 1) und Bit3 (1+1=10 -> 0, Übertrag 1) ein Übertrag passiert ist, der dann bei Bit2 und Bit4 eingetragen wird.
Die nachfolgenden Ausführungen gelten 8051-Prozessoren. Für andere Prozessoren kann etwas anderes gelten.
Das Carry-Flag (C) wird gesetzt, wenn bei Bit7 ein Übertrag passiert ist. Das ist das am häufigst benutzten Flags, weil es bei einer Addition anzeigt, dass das Ergebnis die Maximalgröße des Registers gesprengt hat, oder bei einer Subtraktion anzeigt, dass das Ergebnis kleiner als 0 ist.
218 + 133 = 351 (passt nicht in ein 8-Bit-Register)
Augend 11011010 Addend 10000101 Übertrag 1 =================== Ergebnis 01011111
Das AC-Flag wird gesetzt , wenn bei Bit3 ein Übertrag passiert ist. Das ist für 4-Bit-Operationen gedacht.
11 + 12 = 23 (passt nicht in die unteren 4 Bit)
Augend 00001011 Addend 00001100 Übertrag 1 =================== Ergebnis 00010111
Das OV-Flag wird gesetzt bei Übertrag von Bit7 aber nicht von Bit6 oder Übertrag von Bit6 aber nicht von Bit7. Das ist für vorzeichenbehaftete Zahlen gedacht, wenn sich durch die Operation unerwünscht das Vorzeichen (Bit7) geändert hat.
(-38) + (-123) = (-161) (Ergebnis passt nicht in ein Register)
Augend 11011010 Addend 10000101 Übertrag 1 =================== Ergebnis 01011111
viele grüße
ralphPS: Es heißt "Assembler" (mit 'e'), nicht "Assambler"!
-
Und man kann spannenderweise mit dem Pentium bzw. Debug auch super 8bit compi spielen, zum Beispiel
(debug.exe)-rax AX 0000 :ff -rbx BX 0000 :1 -rdx DX 0000 :64 -rcx CX 0000 :28 -r AX=00FF BX=0001 CX=0028 DX=0064 SP=E082 BP=0000 SI=0000 DI=0000 DS=1E6D ES=1E6D SS=1E6D CS=1E6D IP=0100 NV UP EI PL NZ NA PO NC 1E6D:0100 0000 ADD [BX+SI],AL DS:0001=20 -a 1E6D:0100 add al,bl 1E6D:0102 add dl,cl
Und dann nur noch gucken, was die flags so treiben, wenn die Befehle ausgeführt werden.
Den Instruction Pointer kann man in debug beschreiben mit "rip":
-rip IP 010A :100
-
Danke, ich verstehs jetzt!
Nun habe ich ein Bsp:
Ein Block im internen RAM(Startadresse 20hex, länge=10Bytes) soll gelöscht werden.
In der Schule haben wir es so gemacht:
MOV R1,#20 MOV A,#10 Loop: MOV @R1,#0 INC R1 DEC A JNZ Loop ;springt ja nur wenn A nicht 0 ist
oder so:
MOV R1,#20hex CLEAR: MOV @R1,#0hex INC R1 CJNE R1,#2Ahex,CLEAR ;springe zu clear, wenn der inhalt des Registers R1 ungleich 2Ahex ist oder?
1. Teil:
Warum 2Ahex?
Und könnt ihr mir bitte die Aufgabenstellung genau erklären... Aus was besteht ein Block was ist den damit genau gemeint?
Die Startadresse ist 20hex und was steht in dieser drinnen? irgendein
Binärwert?
Die Länge des Block ist 10 Bytes, was heißt das nun genau?
Erklärt mir bitte die beiden Codes.2. Teil:
Diese JMP-Befehle springen halt irgendwo im Programm herum.Wenn man schreibt:
SJMP rel ;rel ist eine relative 8 - Bit - Offset - Adressse(-128 bis +127) - Was ist eine 8-Bit-Offset-Adresse? Eien Offsetspannung ist jene Spannung die am Eingang angelegt werden muss das am Ausgang 0V rauskommt..., das weiß ich über offset, aber ich kanns net umsetzen. Die Gleiche Frage gilt für adr16 und adr11. LJMP adr16 ;mit LJMP kann überall herumspringen beim 8051er - adr16 ist eien 16bit Adresse AJMP adr11 ;mit AJMP halt nur im 2kbyte-bereich, also kann nur 2kbyte weit springen - adr11 ist eine 11bit adresse ;Bsp: "irgendein wort":.... ; ja und "irgendein wort" ist eine 11bit adresse? und man kann nur 11 bit weit springen? Ich verstehs net... .... AJMP "irgendein wort" ....
Ja und das gleiche bsp mit LJMP und SJMP.
Danke im voraus!
mfg guest123
-
Du machst es schon richtig: Sich in Ruhe Fragen überlegen und fragen. Allerdings ist es besser, den Lehrer als uns zu löchern. Da braucht man zwar eine dicke Haut, weil fragen hierzulande als Beleidigung, Angriff, Verzögerung, Querulantentum etc. gilt, aber anders kommst Du nicht weiter.
guest1234 schrieb:
Ein Block im internen RAM(Startadresse 20hex, länge=10Bytes) soll gelöscht werden.
Warum 2Ahex?
Und könnt ihr mir bitte die Aufgabenstellung genau erklären... Aus was besteht ein Block was ist den damit genau gemeint?Der interne Speicher ist der Speicher, der im Mikrocontroller fest eingebaut ist. Externer Speicher kann bei bestimmten Mikrocontrollern dazugeschaltet werden.
Ein Block ist ein zusammenhängendes Stück von irgendetwas (Blockschokolade, Wohnblock, Notizblock, Ostblock), in diesem Fall ein zusammenhängender Speicherbereich. Der Zusammenhang besteht darin, dass eine bestimmte Anzahl von Speicheradressen mit fortlaufenden Hausnummern adressiert werden und vom Programmierer für einen bestimmten Zweck benutzt werden. Der "bestimmte" Zweck besteht hier nur darin, sie auf Null zu setzen ("zu löschen = engl. clear"), da es sich nur um ein Beispiel handelt.
Wg. 2Ah:
Zähl mal 10 Zahlen ab 20: 20,21,22,23,24,25,26,27,28,29. Wenn Du bei 30 bist, bist Du eins zu weit.
Und nun das Ganze hexadezimal ab 20h: 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h. Wenn Du bei 2Ah bist, bist Du eins zu weit.Die Startadresse ist 20hex und was steht in dieser drinnen? irgendein
Binärwert?Stell Dir das wie eine Straße mit Hausnummern vor: Machen Sie 10 Häuser der Goethestraße ab Hausnummer 20 platt! Was da vorher stand, ist egal, nachher ist alles platt ;).
Die Länge des Block ist 10 Bytes, was heißt das nun genau?
10 Häuser :). Genauer wäre: 10 Speicherzellen mit je einem Byte Größe.
Erklärt mir bitte die beiden Codes.
Der erste Code benutzt eine sogenannte Laufvariable (A). In BASIC wäre das gleichbedeutend mit
FOR A=10 TO 1 STEP -1
. In C hieße esfor (A=10;A>0;A--)
.
Der zweite Code benutzt eine Abbruchbedingung: Wenn die letzte Speicheradresse plus Eins gelöscht werden soll, wird die Schleife verlassen. Das entspricht in einer Hochsprache der WHILE-Schleife.SJMP rel ;rel ist eine relative 8 - Bit - Offset - Adressse(-128 bis +127) - Was ist eine 8-Bit-Offset-Adresse? Eien Offsetspannung ist jene Spannung die am Eingang angelegt werden muss das am Ausgang 0V rauskommt..., das weiß ich über offset, aber ich kanns net umsetzen. Die Gleiche Frage gilt für adr16 und adr11.
Eine "relative Offset-Adresse" ist hier ein "weißer Schimmel". Der Prozessor nimmt die aktuelle Programm-Adresse, zählt 'rel' hinzu und springt dahin. Wenn 'rel' negativ ist, wird eben abgezogen. Wie Du siehst, kann er nicht weiter als 128 Bytes weit springen, dafür ist der Befehl kürzer und schneller als andere Sprungbefehle.
LJMP adr16 ;mit LJMP kann überall herumspringen beim 8051er - adr16 ist eien 16bit Adresse
AJMP adr11 ;mit AJMP halt nur im 2kbyte-bereich, also kann nur 2kbyte weit springen - adr11 ist eine 11bit adresse'adr..' steht für eine absolute Adresse. Dorthin wird gesprungen. Eine 11bit-Adresse steht für eine Adresse am Anfang des Adressenraums (2048 Bytes). Wenn Du einen Controller mit größerem Programmspeicher hast und eine Adresse hinten anspringen willt, musst Du LJMP (Long Jump) nehmen, da hier die Adresse 16 Bits groß sein darf. Dafür braucht der Befehl 1 Byte mehr an Speicherplatz, was - wenn Du wirklich einen großen Controller hast - nicht weiter tragisch ist. Es geht also nicht um "weit springen", sondern um "dahin springen".
"irgendein wort":.... ; ja und "irgendein wort" ist eine 11bit adresse? und man kann nur 11 bit weit springen? Ich verstehs net...
....
AJMP "irgendein wort"
....Fasse das Wort "Wort" in der Computerei nur mit spitzen Fingern an! Ich vermute mal, dass der Lehrer "Label" gemeint hat. Du musst die Einsprungstellen irgendwie bezeichnen ("Loop","CLEAR") und der Assembler berechnet die Adressen. Sollte die Einsprungstelle mit diesem Befehl nicht erreichbar sein (z.B. eine 16-Bit-Adresse soll mit AJMP angesprungen werden), bekommst Du eine Fehlermeldung.
viele grüße
ralph