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 08:13] Ivo Blöchliger [Funktionsweise einer CPU] |
lehrkraefte:blc:informatik:efi-2023:assembler [2024/04/23 15:04] Ivo Blöchliger [Funktionsweise einer CPU] |
||
---|---|---|---|
Line 7: | Line 7: | ||
* Memory mapped output: Die Bytes 232-255 werden als Buchstaben (entsprechend dem ASCII-Code) in der Ausgabe dargestellt. | * 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. | * 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** | **Ausgabe auf die 7-Segment Anzeige** | ||
Line 29: | Line 32: | ||
</ | </ | ||
- | **Subroutine** | + | <WRAP todo> |
+ | Produzieren Sie die Ausgabe ' | ||
+ | </ | ||
+ | **Subroutine, Parameter in Registern** | ||
+ | <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 | ||
- | ====== Assembler ====== | + | ; Params in registers: |
- | * Simulator: https:// | + | ; 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--+ | ||
+ | </ | ||