Upline: Infos & Dokus
Elektronik
Zilog Z8 - Assembler RechteckberechnungDas folgende ist ein Laborprotokoll (1. Labor, Getting Started with Zilog) vom WS2005 des Fachs Microcomputertechnik an der FHTW Berlin, durchgeführt von Prof. Jossifov in den Studienfächern Technische Informatik und Informationstechnik Vernetzte Systeme. Da der Prof so einige Formulierungen bemängelte (nach seiner Meinung uneindeutig) und schon für kleinste Fehler einen Haufen Punkte abzog, gab es darauf nur eine 2.7 - ich habe aber zumind. das meiste beanstandete für diese Onlineversion noch mal überarbeitet. Was jetzt noch fehlen würde, sind einige weitere erklärende Screenshots. AufgabenstellungTask 1Aufgabe 1: Welche Befehle des Programms aus Task 1 nutzen Register Addressing Mode?Aufgabe 2: Welche Adressierungsart verwendet der Z8-Befehl DJNZ? Welcher andere Steuerungsbefehl nutzt die selbe Adressierungsart? Task 2Aufgabe 1: Welchen Unterschied gibt es zwischen den Variablendefinitionen in den Programmen aus Task 1 und Task 2? Welcher Speicher wird im 1. und welcher im 2. Fall benutzt?Aufgabe 2: Warum steht der folgende Sourcecodeauszug am Ende der Hauptfunktion? COUNT db 09H; constant defined ... Kann die Zeile auch hinter der Initialisierung org %000C stehen? Warum? Aufgabe 3: Was passiert auf dem Stack und mit dem Stackpointer bei Ausführung des RET-Befehls? Aufgabe 4: Was ist der Unterschied im Debugger zwischen "Spep over" und "Step into"? Task 3Aufgabe 1: Gibt es Befehle in Task 2 oder 3, die den Direct Addressing Mode nutzen?Aufgabe 2: Welches sind die einzigen Z8-Befehle, die den Direct Addressing Mode nutzen? Task 4Programm schreiben, welches 2 Arrays addiert ...Task 1Zwischenergebnisse der Programmausführung1. Durchlauf:@Addr17h: r8=#00h, r9=#1Eh, flgs=40h (ZF) @Addr 19h r9=#0Fh, flgs=00h @Addr 1Bh: r5=8 2. Durchlauf: r8=#00h, flgs=40h r9=#07h, flgs=80h => r8=#0Fh, flgs=00h, r5=7 3. Durchlauf: r8=#07h, flgs=80h (CF) r9=#83h, flgs=B0h => r8=#16h, flgs=04h, r5=6 4. Durchlauf: r8=#0Bh, flgs=04h (HCF) r9=#41h, flgs=94h => r8=#1Ah, flgs=04h, r5=5 5. Durchlauf: r8=#0Dh r9=#20h, flgs=84h => r8=#1Ch, flgs=04h, r5=4 6. Durchlauf: r8=#0Eh, flgs=04h r9=#10h, flgs=04h, r5=3 7. Durchlauf: r8=#07h r9=#08h, r5=2 8. Durchlauf: r8=#03h, flgs=84h r9=#84h, flgs=34h, r5=1 9. Durchlauf: r8=#01h, flgs=84h r9=#C2h, flgs=24h, r5=0 -> Schleifenende Damit steht das Ergebnis der Multiplikation von 15*30=450 in den Registern r9:r8. Questions
Task 2Questions
Sourcecode;######################################################################################## ;# # ;# Exercise: # ;# Microcontroller Laboratory Exercise with ZILOG DEVELOPER STUDIO 3.68 and Z8 # ;# Simulator # ;# # ;# Task: # ;# The program calculates the area of a trapezium. # ;# Write a function (MultiplyIntegers)that multiplies two integers: 16-bit # ;# unsigned word and an 8-bit unsigned byte. # ;# The multiplication algorithm is the same as the one given in the # ;# "addressingmodes_rectangle.asm", but the counter should be loaded using # ;# indirect register addressing. The addition and division are performed in # ;# the main function, and the multiplication is performed by calling the # ;# "MultiplyIntegers" function. # ;# The lengths of the trapezium are given as 16-bit unsigned words. # ;# The height is given as unsigned 8-Bit integer. # ;# The area of the trapezium is calculated with the formula ((a+c)/2)*h. # ;# When carry is generated from the division by two, the result is rounded # ;# (incremented by 1). The statement jr NC,MultiplyHeight checks for a carry. # ;# If no round is needed the division result is multiplied by the height. # ;# The 16-bit result (the area of trapezium) is stored in SIDE_A. # ;# # ;# Note: # ;# The Carry Flag is found in the Z8 Flag Register (address FCH) # ;######################################################################################## define regfile, org=20H, space=RFILE ;*** RAM memory address allocations - variables *** segment regfile SIDE_A_HI: ds %1 ;high-byte of the trapezium's side A SIDE_A_LO: ds %1 ;low-byte of the trapezium's side A SIDE_C_HI: ds %1 ;high-byte of the trapezium's side C SIDE_C_LO: ds %1 ;low-byte of the trapezium's side C HEIGHT: ds %1 ;trapezium's height ;*** RAM memory address allocations - symbolic address constant**** COUNTER: .equ r15 ;counter used for the multiplication iterations ;**** These are the working register file settings **** STACK: .equ %3F ;Work. Register Group 3, Work. Register F WORKREGS: .equ %10 ;ERF Bank 0, Work. Reg.Group 1 segment code init: org %000C ;COUNT: db 09H srp #WORKREGS ;select a Working Reg. Group for access ld SPL,#STACK ;load the Stack Pointer Low Byte (SPL = control ;register at address FF) ;load the variables with values ld SIDE_A_HI,#0H ;load SIDE_A high-byte with value ld SIDE_A_LO,#06H ;load SIDE_A low-byte with value ld SIDE_C_HI,#0H ;load SIDE_C high-byte with value ld SIDE_C_LO,#05H ;load SIDE_C low-byte with value ld HEIGHT,#04H ;COUNT: db 09H AdditionLow: add SIDE_A_LO,SIDE_C_LO ;add the low bytes of side A and side C jr NC,AdditionHigh ;check for overflow inc SIDE_A_HI ;overflow occurs, so increment the High Byte jr NC,AdditionHigh ret ;END if overflow occurs again AdditionHigh: add SIDE_A_HI,SIDE_C_HI ;add the high bytes of side A and side C jr NC,Division ;if the number is larger than WORD (SIDE_A > 65535) ret ;then Carry Flag = 1; END of program Division: rrc SIDE_A_HI ;Rotate Right Through Carry Flag rrc SIDE_A_LO ;Rotate Right Through Carry Flag (equal to DIV 2) jr NC,MultiplyHeight ;result is muled by HEIGHT if no carry is generated ;from the division rcf ;Reset Carry Flag inc SIDE_A_LO ;round the result(inc by 1) if carry is generated ;from the division jr NC,MultiplyHeight ;no carry (SIDE_A_LO is <255 ), so multiply rcf ;Reset Carry Flag inc SIDE_A_HI ;increment high byte jr NC,MultiplyHeight ;no carry, so multiply ret ;carry = 1, so END of program MultiplyHeight: ld r2, SIDE_A_HI ;load working reg. r2 with the high byte of SIDE_A ld r3, SIDE_A_LO ;load working register r3 with the low byte of SIDE_A ld r4, HEIGHT ;load working register r4 with HEIGHT call MultiplyIntegers ;call function MultiplyIntegers ld SIDE_A_HI, r2 ;load the returned calculated result in SIDE_A ld SIDE_A_LO, r3 ret ;END of program execution COUNT: db 09H ;constant defined in the program memory (ROM ;used for the mul-iterations -> 8 bits + 1 = 9 MultiplyIntegers: ld r0, #high COUNT ;loads R0 with high-byte of the address of COUNT ld r1, #low COUNT ;loads R0 with low-byte of the address of COUNT lde COUNTER,@RR0 ;ld COUNTER cont of addr[RO,R1] (ind.reg.addressing) ;perform the multiplication rcf ;Reset Carry Flag (CF = 0) Loop: rrc R2 rrc R3 jr NC,NextIter add R2,R4 NextIter: djnz COUNTER,Loop ;Decrement COUNTER (COUNTER = COUNTER - 1) and ;Jump to Loop if COUNTER is Not Zero (COUNTER <>0) ret ;end of function Task 3Questions
Sourcecode;######################################################################################## ;# # ;# Exercise: # ;# Microcontroller Laboratory Exercise with ZILOG DEVELOPER STUDIO 3.68 and Z8 # ;# Simulator # ;# # ;# Task: # ;# Write a program that calculates the area of a trapezium. # ;# Implement the function "MultiplyIntegers" using indirect register addressing # ;# It multiplies two integers: 16-bit unsigned word and an 8-bit unsigned byte # ;# The addition and division are performed in the main function, and the # ;# multiplication is performed by calling the "MultiplyIntegers" function. # ;# The lengths of the trapezium are given as 16-bit unsigned words. # ;# The height is given as unsigned 8-Bit integer. # ;# The area of the trapezium is calculated with the formula ((a+c)/2)*h. # ;# When carry is generated from the division by two, the result is rounded # ;# (incremented by 1). The statement jr NC,MultiplyHeight checks for a carry. # ;# If no round is needed the division result is multiplied by the height. # ;# The 16-bit result (the area of trapezium) is stored in SIDE_A. # ;# # ;# Note: # ;# The Carry Flag is found in the the Z8 Flag Register (address FCH) # ;######################################################################################## define regfile, org=20H ,space=RFILE ;*** RAM memory address allocations - variables *** segment regfile SIDE_A: ds %2 ;trapezium's 16-bit side A SIDE_C: ds %2 ;trapezium's 16-bit side C HEIGHT: ds %1 ;trapezium's height ;*** RAM memory address allocations - symbolic address constant**** COUNTER: .equ r15 ;counter used for the multiplication iterations ;**** These are the working register file settings **** STACK: .equ %3F ;Work. Register Group 3, Work. Register F WORKREGS: .equ %10 ;ERF Bank 0, Work. Reg.Group 1 segment code init: org %000C srp #WORKREGS ;select a Working Reg. Group for access ld SPL,#STACK ;load the Stack Pointer Low Byte ;(SPL = control register at address FF) ;perform the initialization ld SIDE_A_HI,#0H ;load SIDE_A high-byte with value ld SIDE_A_LO,#06H ;load SIDE_A low-byte with value ld SIDE_C_HI,#0H ;load SIDE_C high-byte with value ld SIDE_C_LO,#05H ;load SIDE_C low-byte with value ld HEIGHT,#04H ;perform the addition AdditionLow: add SIDE_A_LO,SIDE_C_LO ;add the low bytes of side A and side C jr NC,AdditionHigh ;check for overflow inc SIDE_A_HI ;overflow occurs, so increment the High Byte jr NC,AdditionHigh ret ;END if overflow occurs again AdditionHigh: add SIDE_A_HI,SIDE_C_HI ;add the high bytes of side A and side C jr NC,Division ;if the number is larger than WORD (SIDE_A > 65535) ret ;then Carry Flag = 1; END of program ;perform the division Division: rrc SIDE_A_HI ;Rotate Right Through Carry Flag rrc SIDE_A_LO ;Rotate Right Through Carry Flag (equal to DIV 2) jr NC,MultiplyHeight ;the result is multiplied by HEIGHT if no carry is ;generated from the division rcf ;Reset Carry Flag inc SIDE_A_LO ;round the result(inc 1) if carry is from division jr NC,MultiplyHeight ;no carry (SIDE_A_LO is <255 ), so multiply rcf ;Reset Carry Flag inc SIDE_A_HI ;increment high byte jr NC,MultiplyHeight ;no carry, so multiply ret ;carry = 1, so END of program MultiplyHeight: ld r5,# SIDE_A ;load r5 (input parameter) with the address of SIDE_A ld r4,HEIGHT ;load r4 (input parameter) with HEIGHT call MultiplyIntegers ;call function MultiplyIntegers ret ;end of program COUNT: db 09H ;constant defined in the program memory (ROM); ;used for the mul-iterations -> 8 bits + 1 = 9 ;******************************************************************* ;* This function multiplies an 16-bit unsigned word and an 8-bit unsigned byte. ;* The result is returned in the memory address [r5]. ;* ;* Input parameters: ;* r4 - 8-bit multiplicand (multiplicand is passed by value) ;* r5 - address of the 16-bit multiplier (multiplier is passed by address) ;* Returns: ;* - the calculated result is stored in the memory address that is referenced by r5, i.e. ;* Indirect Register addressing mode is used to store the result ;******************************************************************* MultiplyIntegers: ld r0, #high COUNT ;loads R0 with the HB of address from COUNT ld r1, #low COUNT ;loads R0 with the LB of address from COUNT lde COUNTER,@RR0 ;load COUNTER with the content of address [RO,R1] ;(indirect register addressing) ld r6,r5 ;r6 = adresse of HB from 16-bit-number inc r6 ;gets adress of the LB from the 16-bit-number rcf ;Reset Carry Flag (CF = 0) Loop: rrc @r5 rrc @r6 jr NC,NextIter ld r7,@r5 ;the z8 needs for add-destination a register add r7,r4 ;this causes in the use of a temp-varible (r7) ld @r5,r7 ;and back to @r5 djnz COUNTER,Loop ;Decrement COUNTER (COUNTER = COUNTER - 1) and ;Jump to Loop if COUNTER is Not Zero (COUNTER <>0) ret ;end of function Task 4Sourcecodedefine regfile, org=20H ,space=RFILE segment regfile ;*** Array *** array: db %5, 4, 3, 2, 1, 11, 12, 13, 14, 15 ;*** temporary variables - RAM memory address allocations **** COUNTER: .equ r15 ;counter used for the multiplication iterations OFFSET: .equ r14 ;adress:=segmentsize*segmentnumber+offset ;**** These are the working register file settings **** WORKREGS: .equ %10 ;ERF Bank 0, Work. Reg.Group 1 segment code init: org %000C srp #WORKREGS ;select a Working Reg. Group for access ld OFFSET,#0H ;offset is 0 ld COUNTER,#05H ;wanna have 5 additions Loop: ld r3,20H(r14) ;load the 1./2./3./4./5. value from array into r3 ld r4,25H(r14) ;load the 6./7./8./9./10. value from array into r4 add r3,r4 ;add both values -> result is in r3 ld 20H(r14),r3 ;store result r3 into 1./2./3./4./5. field of array inc OFFSET ;set offset to next arrayfield djnz COUNTER,Loop ;while COUNTER <> 0 do loop ret ;end of program |