Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| lehrkraefte:blc:informatik:efi-2023:assembler [2024/04/02 09:00] – [Hackme] Ivo Blöchliger | lehrkraefte:blc:informatik:efi-2023:assembler [2024/04/23 13:04] (current) – [Funktionsweise einer CPU] Ivo Blöchliger | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Funktionsweise einer CPU ====== | ||
| + | * Speicher: Array of Bytes, Index wird **Adresse** genannt. Hier laufen die Adressen von 0-255. | ||
| + | * Register: Eine Art interne Variablen in der CPU. Hier A,B,C,D, Grösse 1 Byte | ||
| + | * Instruction Pointer (IP): Gibt an, wo die nächste auszuführende Instruktion im Speicher liegt. Wird oft auch Programm Counter (PC) genannt. | ||
| + | * Stack Pointer (SP): Zeigt auf den ersten freien Platz auf dem Stapel (wächst rückwärts). Startet bei Adresse 231. | ||
| + | * Flags: Z (Zero, True wenn ein Ergebnis Null ist), C (Carry, True wenn ein Überlauf stattgefunden hat). F ist True, wenn ein Fehler aufgetreten ist (z.B. eine nicht existente Instruktion, | ||
| + | * Memory mapped output: Die Bytes 232-255 werden als Buchstaben (entsprechend dem ASCII-Code) in der Ausgabe dargestellt. | ||
| + | * Die Bytes 253-255 werden zusätzlich in der Siebensegmentanzeige dargestellt. Die Segmente sind von oben im Uhrzeigersinn nummeriert (Bits 0 bis 5), mit dem inneren Segment mit Nummer 6. | ||
| + | |||
| + | |||
| + | * Simulator: https:// | ||
| + | |||
| + | **Ausgabe auf die 7-Segment Anzeige** | ||
| + | <code asm> | ||
| + | MOV [253], 119 | ||
| + | MOV [254], 124 | ||
| + | MOV [255], 57 | ||
| + | </ | ||
| + | |||
| + | **For-Loop** | ||
| + | <code asm> | ||
| + | MOV A, 10 ; loop counter | ||
| + | MOV B, 232 ; start output address | ||
| + | MOV C, ' | ||
| + | loop: | ||
| + | MOV [B], C ; Write letter to address pointed at by B | ||
| + | INC B ; Increase output position | ||
| + | INC C ; Increase letter | ||
| + | DEC A ; Decrease loop counter | ||
| + | JNZ loop ; last result not zero? Then jump to loop | ||
| + | HLT | ||
| + | </ | ||
| + | |||
| + | <WRAP todo> | ||
| + | Produzieren Sie die Ausgabe ' | ||
| + | </ | ||
| + | **Subroutine, | ||
| + | |||
| + | <code asm> | ||
| + | start: | ||
| + | MOV C,232 ; Address in to C | ||
| + | MOV B,4 ; Digit in to B | ||
| + | CALL showDigit | ||
| + | MOV B,2 ; new digit in B | ||
| + | INC C ; Increase address | ||
| + | CALL showDigit | ||
| + | HLT | ||
| + | |||
| + | ; Params in registers: | ||
| + | ; B digit to print (as a number 0-9) | ||
| + | ; C address where to print | ||
| + | showDigit: | ||
| + | PUSH B ; Save B onto the stack | ||
| + | ADD B,' | ||
| + | MOV [C], B ; Write ASCII to address pointed by C | ||
| + | POP B ; Restore B from the stack | ||
| + | RET ; Return | ||
| + | |||
| + | |||
| + | </ | ||
| + | Eine subroutine sollte Register nicht verändern. Braucht man trotzdem Register, sollen diese erst auf den Stack gesichert und danach wieder vom Stack in umgekehrter Reihenfolge wieder hergestellt werden. | ||
| + | |||
| + | Der '' | ||
| + | |||
| + | Es ist darum absolut notwendig, dass SP vor dem '' | ||
| + | |||
| + | **Subroutine, | ||
| + | <code asm> | ||
| + | MOV A,42 ; set A | ||
| + | PUSH 13 ; we want mod 13, so push it onto the stack | ||
| + | CALL mod ; call mod | ||
| + | INC SP ; correct Stack-Pointer (Same as POP, but ignore value) | ||
| + | HLT ; Result now in register A | ||
| + | |||
| + | |||
| + | |||
| + | ; Computes A mod X, where X is on the stack | ||
| + | ; Result will be in A | ||
| + | mod: | ||
| + | PUSH B ; Save B | ||
| + | PUSH A ; Save A | ||
| + | DIV [SP+4] | ||
| + | MUL [SP+4] | ||
| + | MOV B,A ; B = A - A % X | ||
| + | POP A ; restore A | ||
| + | SUB A,B ; now A = A % X | ||
| + | POP B ; restore B | ||
| + | RET ; return, result in A | ||
| + | |||
| + | </ | ||
| + | |||
| + | <WRAP todo> | ||
| + | Unter Verwendung der obigen Beispiele und subroutinen, | ||
| + | |||
| + | <hidden Lösungsvorschlag> | ||
| + | <code asm> | ||
| + | MOV A, 237 | ||
| + | MOV C,232 | ||
| + | CALL showByte | ||
| + | HLT | ||
| + | |||
| + | ; Byte in A | ||
| + | ; Address in C | ||
| + | showByte: | ||
| + | PUSH A ; Save registers | ||
| + | PUSH B | ||
| + | PUSH C | ||
| + | ADD C,2 | ||
| + | loopA: | ||
| + | PUSH A ; SAVE A | ||
| + | PUSH 10 ; Push modulo op to stack | ||
| + | CALL mod | ||
| + | INC SP ; Correct Stackpointer | ||
| + | MOV B,A ; digit to B | ||
| + | CALL showDigit | ||
| + | DEC C ; Adjust for next address | ||
| + | POP A ; restore A | ||
| + | DIV 10 | ||
| + | JNZ loopA | ||
| + | POP C | ||
| + | POP B | ||
| + | POP A | ||
| + | RET | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | **Verzweigungen (if, else)** | ||
| + | <code asm> | ||
| + | MOV A, 42 ; 1st value to compare | ||
| + | MOV B, 23 ; 2nd value to compare | ||
| + | CMP A,B ; Compare (subtraction, | ||
| + | JB less ; Carry flag set? then it's less | ||
| + | JE equal ; Zero flag set, then it's equal | ||
| + | MOV [232],'>' | ||
| + | JMP endif ; Jump to 'after if' | ||
| + | less: | ||
| + | MOV [232],'<' | ||
| + | JMP endif | ||
| + | equal: | ||
| + | MOV [232],' | ||
| + | |||
| + | endif: | ||
| + | HLT | ||
| + | |||
| + | </ | ||
| + | <WRAP todo> | ||
| + | Schreiben Sie eine oder mehrere Subroutinen, | ||
| + | </ | ||
| + | |||
| + | **Arrays** | ||
| + | Studieren Sie folgenden Sortier-Algorithmus: | ||
| + | <code asm> | ||
| + | JMP start | ||
| + | arrayStart: | ||
| + | DB ' | ||
| + | DB ' | ||
| + | DB ' | ||
| + | DB ' | ||
| + | DB ' | ||
| + | DB ' | ||
| + | |||
| + | |||
| + | start: ; copy to output aerea | ||
| + | MOV A, arrayStart | ||
| + | MOV B, 232 | ||
| + | copyLoop: | ||
| + | MOV C,[A] | ||
| + | MOV [B],C | ||
| + | INC A | ||
| + | INC B | ||
| + | CMP A,start | ||
| + | JNE copyLoop | ||
| + | |||
| + | ; Write len variable, setup start address | ||
| + | MOV A, start | ||
| + | MOV B, arrayStart | ||
| + | SUB A,B | ||
| + | ADD A,232 | ||
| + | MOV [last], A | ||
| + | MOV A, 232 | ||
| + | ; Start sorting | ||
| + | loopA: | ||
| + | MOV B,A | ||
| + | loopB: | ||
| + | INC B | ||
| + | CMP B,[last] | ||
| + | JNC nextA | ||
| + | MOV C,[A] | ||
| + | MOV D,[B] | ||
| + | CMP C,D | ||
| + | JBE loopB | ||
| + | MOV [A],D | ||
| + | MOV [B],C | ||
| + | JMP loopB | ||
| + | nextA: | ||
| + | INC A | ||
| + | CMP A,[last] | ||
| + | JB loopA | ||
| + | HLT | ||
| + | last: | ||
| + | DB 0 | ||
| + | </ | ||
| + | |||
| + | **Ziffern auf 7-Segment-Anzeige** | ||
| + | <WRAP todo> | ||
| + | Mit Hilfe eines Arrays, schreiben Sie eine subroutine, die eine Ziffer auf der 7-Segment-Anzeige ausgibt. | ||
| + | |||
| + | Zusatz: Geben Sie ein Byte auf der 7-Segmentanzeige dezimal aus. | ||
| + | |||
| + | Bonus: Implementieren Sie QuickSort. | ||
| + | |||
| + | <hidden Animationen auf 7-Segment-Anzeige> | ||
| + | <code asm> | ||
| + | ; Simple example | ||
| + | ; Writes Hello World to the output | ||
| + | |||
| + | start: | ||
| + | |||
| + | MOV B, dataStart | ||
| + | loop: | ||
| + | MOV A, 253 | ||
| + | MOV C, [B] | ||
| + | MOV [A], C | ||
| + | MOV C, [B+1] | ||
| + | MOV [A+1], C | ||
| + | MOV C, [B+2] | ||
| + | MOV [A+2], C | ||
| + | ADD B, 3 | ||
| + | CMP B, dataEnd | ||
| + | JNZ loop | ||
| + | JMP start | ||
| + | |||
| + | |||
| + | |||
| + | dataStart: | ||
| + | DB 8 | ||
| + | DB 8 | ||
| + | DB 8 | ||
| + | |||
| + | DB 0 | ||
| + | DB 8 | ||
| + | DB 12 | ||
| + | |||
| + | DB 0 | ||
| + | DB 0 | ||
| + | DB 14 | ||
| + | |||
| + | DB 0 | ||
| + | DB 0 | ||
| + | DB 7 | ||
| + | |||
| + | DB 0 | ||
| + | DB 1 | ||
| + | DB 3 | ||
| + | |||
| + | DB 1 | ||
| + | DB 1 | ||
| + | DB 1 | ||
| + | |||
| + | DB 33 | ||
| + | DB 1 | ||
| + | DB 0 | ||
| + | |||
| + | DB 49 | ||
| + | DB 0 | ||
| + | DB 0 | ||
| + | |||
| + | DB 56 | ||
| + | DB 0 | ||
| + | DB 0 | ||
| + | |||
| + | DB 24 | ||
| + | DB 8 | ||
| + | DB 0 | ||
| + | |||
| + | dataEnd: | ||
| + | </ | ||
| + | </ | ||
| + | <hidden Animation mit Bytes in Strings codier (unnötig hackisch)> | ||
| + | <code asm> | ||
| + | start: | ||
| + | |||
| + | MOV B, dataStart | ||
| + | loop: | ||
| + | MOV C, [B] | ||
| + | MOV A, [B+6] | ||
| + | MOV [253], C | ||
| + | MOV [254], A | ||
| + | MOV [255], C | ||
| + | INC B | ||
| + | CMP B, dataEnd | ||
| + | JNZ loop | ||
| + | JMP start | ||
| + | |||
| + | |||
| + | |||
| + | dataStart: | ||
| + | DB " | ||
| + | |||
| + | dataEnd: | ||
| + | DB " | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | <hidden Quicksort-Implementation> | ||
| + | <code asm> | ||
| + | JMP start | ||
| + | arrayStart: | ||
| + | DB 4 | ||
| + | DB 2 | ||
| + | DB 7 | ||
| + | DB 9 | ||
| + | DB 8 | ||
| + | DB 7 | ||
| + | DB 4 | ||
| + | DB 5 | ||
| + | DB 8 | ||
| + | DB 9 | ||
| + | DB 4 | ||
| + | DB 3 | ||
| + | DB 6 | ||
| + | DB 1 | ||
| + | |||
| + | |||
| + | start: | ||
| + | MOV A, arrayStart | ||
| + | MOV B, start | ||
| + | DEC B | ||
| + | call quicksort | ||
| + | HLT | ||
| + | |||
| + | |||
| + | quicksort: | ||
| + | ;first elements address in A | ||
| + | ;last elements address in B | ||
| + | PUSH D | ||
| + | PUSH C | ||
| + | PUSH B | ||
| + | PUSH A | ||
| + | MOV C,B | ||
| + | SUB C,A | ||
| + | JBE ende ; bail if B-A <= 0 | ||
| + | MOV [a0], A ; save bounds | ||
| + | MOV [b0], B | ||
| + | MOV C, [A] ; Pivot value | ||
| + | INC A | ||
| + | leftloop: | ||
| + | CMP C,[A] | ||
| + | JC rightloop | ||
| + | INC A | ||
| + | CMP A,B | ||
| + | JBE leftloop | ||
| + | |||
| + | rightloop: | ||
| + | CMP C,[B] | ||
| + | JA swapping | ||
| + | DEC B | ||
| + | CMP A,B | ||
| + | JB rightloop | ||
| + | |||
| + | swapping: | ||
| + | CMP A,B | ||
| + | JAE setpivot | ||
| + | MOV D, [A] | ||
| + | PUSH D | ||
| + | MOV D, [B] | ||
| + | MOV [A], D | ||
| + | POP D | ||
| + | MOV [B], D | ||
| + | INC A | ||
| + | DEC B | ||
| + | JMP leftloop | ||
| + | |||
| + | setpivot: | ||
| + | CMP A,[b0] | ||
| + | JBE ok | ||
| + | MOV A,[b0] | ||
| + | INC A | ||
| + | ok: ; swap pivot and [A] | ||
| + | DEC A | ||
| + | MOV [p0], A ; index of pivot | ||
| + | MOV D,[A] | ||
| + | MOV [A], C | ||
| + | MOV C,[a0] | ||
| + | MOV [C], D | ||
| + | ;recursion | ||
| + | MOV A, [a0] | ||
| + | MOV B, [p0] | ||
| + | DEC B | ||
| + | PUSH [p0] ; save p0 and b0 | ||
| + | PUSH [b0] | ||
| + | call quicksort | ||
| + | POP B ; restore p0 and b0 | ||
| + | POP A | ||
| + | INC A | ||
| + | call quicksort | ||
| + | ende: | ||
| + | POP A | ||
| + | POP B | ||
| + | POP C | ||
| + | POP C | ||
| + | RET | ||
| + | |||
| + | |||
| + | a0: DB 0 | ||
| + | b0: DB 0 | ||
| + | p0: DB 0 | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | ===== Hackme ===== | ||
| + | * Studieren Sie den Code. | ||
| + | * Ändern Sie den String in der DB Zeile, so, dass '' | ||
| + | <code asm> | ||
| + | ; Dieses Programm gibt den String rechtsbündig ab | ||
| + | ; Adresse 250 aus. | ||
| + | ; | ||
| + | JMP start | ||
| + | DB "hello world" | ||
| + | ; | ||
| + | ; Register | ||
| + | ; A Ausgabe-Adresse | ||
| + | ; B Position in DB | ||
| + | ; C temporär | ||
| + | |||
| + | start: MOV A,250 ; Adresse Ausgabe (letzter Buchstabe) | ||
| + | MOV B, start ; Adresse+1 vom letzten Buchstaben | ||
| + | DEC B ; B vermindern | ||
| + | CALL ausgabe | ||
| + | HLT | ||
| + | ausgabe: | ||
| + | MOV C,[B] ; Buchstabe in C | ||
| + | MOV [A],C ; Ausgabe | ||
| + | DEC A ; A vermindern | ||
| + | DEC B ; B vermindern | ||
| + | CMP B,1 ; ist B am Anfang angekommen? | ||
| + | JNE ausgabe ; sonst wiederholen | ||
| + | RET | ||
| + | </ | ||
| + | <hidden Hinweise> | ||
| + | Welcher für die Programmausführung wichtiger Bereich wird bei zu langem String überschrieben? | ||
| + | <hidden weitere Hinweise> | ||
| + | Finden Sie eine Eingabe so, dass die Rücksprungadresse manipuliert wird (z.B. Rücksprung auf start). | ||
| + | <hidden noch mehr Hinweise> | ||
| + | Platzieren Sie den gewünschten Assemblercode im String und setzen Sie die Rücksprungadresse darauf. | ||
| + | <hidden Ausgabe vom Assemblercode als String> | ||
| + | <code asm> | ||
| + | lol: | ||
| + | MOV [253], 0111000b | ||
| + | MOV [254], 0111111b | ||
| + | MOV [255], 0111000b | ||
| + | |||
| + | fertig: | ||
| + | mov A, fertig | ||
| + | dec A | ||
| + | mov B, 246 | ||
| + | loop: | ||
| + | mov C, [A] | ||
| + | mov [B], C | ||
| + | dec B | ||
| + | dec A | ||
| + | JNC loop | ||
| + | hlt | ||
| + | |||
| + | </ | ||
| + | <hidden mögliche Lösungen> | ||
| + | Mit Rücksprung direkt in die DB-Konstante (Adresse 0x02) | ||
| + | <code asm> | ||
| + | DB " | ||
| + | </ | ||
| + | Oder mit Rücksprung in die kopierten Daten an der Adresse 0xdc (was realistischer ist, wenn der String eine Eingabe sein soll): | ||
| + | <code asm> | ||
| + | DB " | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== Mögliche Prüfungsfragen ===== | ||
| + | Die Ausgabe auf die drei 7-Segment Anzeigen erfolgt auf die Adressen 253 bis 255. | ||
| + | |||
| + | Die Bits auf der Anzeige sind wie folgt nummeriert: | ||
| + | <code txt> | ||
| + | +--0--+ | ||
| + | 5 1 | ||
| + | :--6--: | ||
| + | 4 2 | ||
| + | +--3--+ | ||
| + | </ | ||