9. Assemblerprogrammering


9.1 Handassemlering/disassemblering

9.1.1 Översätt följande sekvens av assemblerdirektiv för FLIS-assemblatorn till maskinkod (assemblera programmet). Komplettera figuren så att det klart framgår hur maskinkod och assemblerkod hör ihop och vilka minnesadresser maskinkoden är placerad på.

9.1.2 Följande figur illustrerar några fragment minne hos en FLISP-dator. I minnet finns en ”branch”-instruktion samt dess mål indikerade. Bestäm instruktionens operand, dvs. det värde som finns lagrat på adress 5A. OPERAND = Adress – (PC+2) = 81 – (59+2) = 26 (Alla adressvärden på hexadecimal form)

9.1.3 Följande figur illustrerar några fragment minne hos en FLISP -dator. I minnet finns en ”branch”-instruktion samt dess mål indikerade. Bestäm instruktionens operand, dvs. det värde som finns lagrat på adress 63. OPERAND = Adress – (PC+2) = 10 – (62+2) = AC (Alla adressvärden på hexadecimal form)

9.1.4 Översätt följande assemblerprogram för FLISP till maskinkod (assemblera programmet). Komplettera figuren så att det klart framgår hur maskinkod och assemblerkod hör ihop och vilka minnesadresser maskinkoden är placerad på.

9.1.5 Översätt följande assemblerprogram för FLISP till maskinkod (assemblera programmet). Komplettera figuren så att det klart framgår hur maskinkod och assemblerkod hör ihop och vilka minnesadresser maskinkoden är placerad på.

9.1.6 Ur en FLISP-dators minne avläser vi följande minnesinnehåll (hexadecimalt):

90,48,91,94,F5,24,03,EB,21,FA,21,FE

Utgå i från att ett program är lagrat här med början på adress 2016. Identifiera instruktionssekvensen, dvs. disassemblera minnesinnehållet.
20:     LDX  #start	
22:     LDY  #dest
24: L1: LDA  ,X+
25:     BEQ  L2
27:     STA  ,Y+
28:     BRA  L1
2A: L2: BRA  L2	

9.1.7 Ur en FLISP-dators minne avläser vi följande minnesinnehåll (hexadecimalt):

F1,7A,06,0E,A6,C4,A5,C5,24,02,F0,01,21,FE

Utgå i från att ett program är lagrat här med början på adress 2016. Identifiera instruktionssekvensen, dvs. disassemblera minnesinnehållet.
20:     LDA   $7A	
22:     NEGA
23:     RORA
24:     ADDA  $C4
26:     ADCA  $C5
28:     BEQ   L2
2A:     LDA   #1
2C: L2: BRA   L2	

9.2 Globala variabler och tilldelningar

9.2.1 Utgå från att data placeras från adress 0 till 0x1F och att programkodkod placeras på adress 0x20 och uppåt. Vi har följande deklarationer i programspråket C:

char ga,gb,gc; char gd = 0x10;

I C-programmet utförs följande tilldelningssatser:
gc = 5;
ga = gb = gd;
a) Visa, med FLISP-assembler och figur, hur data och kod placeras i minnet. b) Visa, hur innehållet i minnets datadel ändrats efter det att tilldelningssatserna utförts.

9.2.2 Antag att följande variabeldeklaration har gjorts:

char ga;

Låt vidare symbolen portFB beteckna adressen FB16 och på samma sätt symbolenportFC beteckna adressen FC16 i FLISP-datorns adressrum. Låt dessutom beteckningen*portFx (stjärna framför symbolnamnet) beteckna innehållet på den symboliska adressen. a) Visa, med lämpliga assemblerdirektiv, hur variabeln och adressymbolerna deklareras i FLISP assembler.
ga:     RMB   1
portFB: EQU   $FB
portFC: EQU   $FC
Visa hur följande tilldelningar kodas i FLISP assembler: b)ga= *portFB;
   LDA   portFB
   STA   ga
c)*portFC = ga;
   LDA   ga
   STA   portFC
d)*portFC = *portFB;
   LDA   portFB
   STA   portFC

9.2.3 Antag att följande variabeldeklarationer gjorts:

char ga,i; char v[10];

a) Översätt deklarationerna till direktiv i FLISP-assembler.
ga:  RMB   1
i:   RMB   1
v:   RMB   10
Visa hur följande tilldelningar kodas i FLISP assembler: b)ga = v[1];
   LDA   v+1
   STA   ga
c)v[5] = ga;
   LDA   ga
   STA   v+5
d)ga = v[i];
   LDX   #v
   LDA   i
   LDA   A,X
   STA   ga
e)v[i] = ga;
   LDX   #v
   LDA   i
   LEAX  A,X
   LDA   ga
   STA   0,X

9.3 Uttrycksevaluering

9.3.1 Komplettera följande tabeller som anger operander och operatorer, med de resulterande uttryckens värden. Operanderna anges på decimal form. Ange resultaten på hexadecimal form med storlek byte. a) Aritmetiska operationer b) Bitvis operationer c) Skiftoperationer d) Sanningsuttryck

9.3.2 Utgå från att data placeras från adress 0 till 0x1F och att programkodkod placeras på adress 0x20 och uppåt. Vi har följande deklarationer i programspråket C:

char ga,gb,gc;

I C-programmet utförs följande tilldelningssatser:
gc = 38;
gb = ~gc;
ga = (gc>>1) + gb - 5;
Översätt deklarationer och programkod till FLISP-assembler.
    ORG	data
ga:	RMB	1
gb:	RMB	1
gc:	RMB	1

    ORG	kod
	LDA	#38
	STA	gc
	COMA
	STA	gb
	LDA	gc
	LSRA
	ADDA	gb
	SUBA	#5
	STA	ga

9.3.3 Antag att följande variabeldeklarationer har gjorts:
char a, b;
Visa en kodsekvens som evaluerar resultatet av följande uttryck till register A.
(((a&b) | 8 ) ^ 0x33 )
   LDA   a      ; A = a
   ANDA  b      ; A = (a&b)
   ORA   #8     ; A = (a&b)|8
   EORA  #$33   ; A = ((a&b)|8)^0x33)

9.3.4 Antag att följande variabeldeklarationer har gjorts:
char a, b, c, d;
Visa en kodsekvens som evaluerar resultatet av följande uttryck till register A.
(((a|4) & c ) ^ d )
   LDA   a      ; A = a
   ORA   #4     ; A = (a|4)
   ANDA  c      ; A = (a|4)&c
   EORA  d      ; A = ((a|4)&c ^d)

9.3.5 Antag att följande variabeldeklarationer har gjorts:
char a, b, c;
Visa en kodsekvens som evaluerar resultatet av följande uttryck till register A.
( (a+b) -5 )
   LDA   a      ; A = a
   ADDA  b      ; A = (a+b)
   SUBA  #5     ; A = (a+b)-5

9.3.6 Antag att följande variabeldeklarationer har gjorts:
signed char a, b;
Visa en kodsekvens som evaluerar resultatet av följande uttryck till register A.
( ( (a>>1) +b) <<1)
   LDA   a      ; A = a
   ASRA         ; A = a>>1
   ADDA  b      ; A = (a>>1)+b
   LSLA         ; A = ((a>>1)+b)<<1

9.3.7 Antag att följande variabeldeklarationer har gjorts:
char a;
Visa en kodsekvens som evaluerar resultatet av följande uttryck till register A.
( (a<<1) +1) >>2)
   LDA   a     ; A = a
   LSLA	       ; A = a<<1
   ADDA  #1    ; A = (a<<1)+1
   LSRA        ; A = ((a<<1)+1)<<1
   LSRA        ; A = ((a<<1)+1)<<2

9.3.8 Antag att följande deklarationer gjorts:
char i,j;
char v[10];
Visa hur adressen till följande uttryck evalueras till register X, kodat i FLISP assembler: a)v[i+1];
   LDX   #v
   LDA   i
   ADDA  #1
   LEAX  A,X
b)v[i-j];
   LDX   #v
   LDA   i
   SUBA  j
   LEAX  A,X
c)v[i+(j & 1)];
   LDX   #v
   LDA   j
   ANDA  #1
   ADDA  i
   LEAX  A,X

9.3.9 Antag att följande deklarationer gjorts:
char ca,cb;
char va[5], vb[10]
a) Översätt deklarationerna till FLISP-assembler.
ca:   RMB   1
cb:   RMB   1
va:   RMB   5
vb:   RMB   10
Visa hur följande uttrycksevalueringar och tilldelningar kodas i FLISP assembler: b)ca = va[0];
   LDA   va
   STA   ca
c)va[0]=ca;
   LDA   ca
   STA   va
d)cd = va[3];
   LDX   #va
   LDA   3,X
   STA   cd
(alternativt)
   LDA   ca+3
   STA   cd
e)cb = va[ca];
   LDX   #va
   LDA   ca
   LDA   A,X
   STA   cb
( alternativt)
   LDX   ca
   LDX   va,X
   STX   cb
f)cb = va[vb[ca]];
   LDX   ca
   LDX   vb,X
   LDX   va,X
   STX   cb
g)va[ca]=vb[cb];
   LDX   cb
   LDA   vb,X
   LDY   ca
   LEAY  va,Y
   STA   0,Y

9.4 Programflödeskontroll

9.4.1
Två strömställare (DIL-switch) är anslutna till inportar med adresser FB16 och FC16 i en FLISP-dator. Dessutom är en ljusdiodramp (Bargraph) ansluten till en utport med adress FC16. Låt symbolenportFB beteckna adressen FB16 och på samma sätt symbolenportFC beteckna adressen FC16 i FLISP-datorns adressrum. Låt dessutom beteckningen*portFx ( stjärna framför symbolnamnet) beteckna innehållet på den symboliska adressen. Ett program,main, som kontinuerligt bildar bitvis logiskt ELLER av värdena som läses från strömbrytarna och skriver detta till ljusdiodrampen kan utformas enligt: void main( void ) { while( 1 ) { *portFC = *portFB | *portFC; } } Visa hur programmet kodas i FLISP assembler:

portFB: EQU   $FB
portFC:	EQU   $FC

main:   LDA   portFB
        ORA   portFC
        STA   portFC
        BRA   main


9.4.2 Betrakta U som ett tal [0,255]. För vilka värden på U utförs programflödesändringen nedan?
   LDA        #$85
   CMPA       #U
   B(Villkor) Hopp
om den villkorliga instruktionen är a) BHI e) BGT b) BHS f) BGE c) BLS g) BLE d) BLO h) BLT

9.4.3 Följande programavsnitt är givet med samma symbolbeteckningar som i uppgift 9.4.1. Visa en kodsekvens i FLISP-assembler, som motsvarar programavsnittet. while( *portFB > 0 ) { *portFC = *portFB; } while(1) { *portFC = 0xFF; }
portFC: EQU   $FC
portFB: EQU   $FC

while_1_continue:
   LDA   portFB
   BMI   while_1_break

while_1_do:
   LDA   portFB
   STA   portFC
   BRA   while_1_continue

while_1_break:

while_2:
   LDA   #$FF
   STA   portFC
   BRA   while_2

9.4.4 Använd samma symbolbeteckningar som i uppgift 9.4.1. Visa en kodsekvens i FLISP-assembler, som motsvarar följande programavsnitt. if( *portFB > 10 ) *portFC = 1; else *portFC = 0xFF;
portFC: EQU   $FC
portFB: EQU   $FC

   LDA   portFB   ; if( *portFB > 10 )
   CMPA  #10
   BLO   If_else
   LDA   #1       ; *portFC = 1
   STA   portFC
   BRA   If_end

If_else:
   LDA   #$FF     ; *portFC = 0xFF
   STA   portFC

If_end:

9.4.5 Använd samma symbolbeteckningar som i uppgift 9.4.1. Visa en kodsekvens i FLISP-assembler, som motsvarar följande programavsnitt. if( *portFB & 1 ) *portFC = 0xFF; else *portFC = 0;
portFC: EQU   $FC
portFB: EQU   $FC

   LDA   portFB    ; if( *portFB & 1 )
   ANDA  #1
   BEQ   If_else   
   LDA   #$FF      ; *portFC = 0xFF
   STA   portFC
   BRA   If_end

If_else:
   CLRA            ; *portFC = 0
   STA   portFC

If_end:

9.4.6 Använd samma symbolbeteckningar som i uppgift 9.4.1. Visa hur följande programkonstruktion kodas i FLISP-assembler. Programkod ska placeras med start på adress 2016, data placeras med start på adress 0. signed char g; void main( void ) { while( 1 ) { g = *portFC; if( ( g & 2 ) && ( g < 100 ) ) *portFC = 1; else *portFC = 0; } }
portFC: EQU   $FC
   ORG   0
g: RMB   1

   ORG   $20
main:
   LDA   portFC     ; g = *portFC
   STA   g
   ANDA  #2         ; if( g & 2 )
   BEQ   If_else
   CMPA  #100       ; if( g < 100 )
   BHI   If_else
   LDA   #1         ; *portFC = 1
   STA   portFC
   BRA   If_end
If_else:
   CLRA             ; *portFC = 0
   STA   If_end
If_end:
   RTS

9.4.7 Använd samma symbolbeteckningar som i uppgift 9.4.1. Visa hur följande programkonstruktion kodas i FLISP-assembler. Programkod ska placeras med start på adress 2016, data placeras med start på adress 0. signed char e, g; void main( void ) { g = *portFC; while( g > 0 ) { e = *portFB; if( e > 64 ) break; if( e < 32 ) continue; g = g-1; } }
portFC: EQU   $FC
portFB: EQU   $FB
        ORG   0
e: RMB   1
g: RMB   1

   ORG   $20
main:
   LDA   portFC          ; g = *portFC
   STA   g

while_continue:
   LDA   g               ; while( g > 0 )
   BNE   while_break

   LDA   portFB          ; e = *portFB
   STA   e

   CMPA  #64             ; if( e > 64 )
   BHI   while_break     ; break;

   CMPA  #32             ; if( e < 32)
   BCS   while_continue  ; continue

   DEC   g               ; g = g–1;
   BRA   while_continue

   RTS

9.5 Stackanvändning, parametrar och returvärden

9.5.1 Följande program finns lagrat i en FLISP-dators minne: ; Huvudprogram 20: LDSP #$F0 22: LDX #$50 24: PSHX 25: JSR $40 27: STA $E0 29: JMP $10 ; Subrutin 1 40: PSHA 41: PSHX 42: PSHC 43: LDX #$E0 45: LDA #$03 47: JSR $60 49: PULC 4A: PULX 4B: PULA 4C: RTS ; Subrutin 2 60: PSHA 61: PSHC 62: PSHX 63: LDX #$15 65: INCA 66: PULX 67: PULC 68: PULA 69: RTS Beskriv stackens utseende, dvs. komplettera följande tabell, då programräknaren PC har följande värden:

9.5.2 Antag att följande deklarationer gjorts:
char e,c,d;
Dessutom är funktionernachar f1(void), char f2(char) och char f3(char,char) definierade. Visa hur följande tilldelningar från funktionsanrop kodas i FLISP-assembler: a) e = f1( ); Konventionen säger att funktioner ska returnera värdet i register A, vi får därför:
   JSR   f1
   STA   e
b) e = f2( c ); Konventionen säger att funktioner ska returnera värdet i register A. Då en funktion har exakt en parameter skickas denna i register A. Vi får därför:
   LDA   c
   JSR   f2
   STA   e
c) e = f3( c, d ); Konventionen säger att funktioner ska returnera värdet i register A. Då en funktion har fler än en parameter skickas samtliga dessa via stacken. Observera att parameterlistan bearbetas från höger till vänster. Vi får då:
   LDA   d
   PSHA
   LDA   c
   JSR   f2
   LEASP 2,SP
   STA   e

9.5.3 Antag att följande deklarationer gjorts:
char p,q;
Dessutom är funktionenchar h(char) definierad. Visa hur följande tilldelningssats kodas i FLISP-assembler:
q = p - h(p);
   LDA   p  ; A = h(p)
   JSR   h
   NEGA     ; A = -h(p)
   ADDA  p  ; A = p-h(p)
   STA   q  ; q = p-h(p)


9.5.4 Antag att följande deklarationer gjorts:
char i,p,v[5];
Dessutom är funktionenchar h(char) definierad. Visa hur följande tilldelningssats kodas i FLISP-assembler:
v[i] = p + h(p);
   LDA   p
   JSR   h   ; A = h(p)
   ADDA  p   ; A = p+h(p)
   LDX   i   ; X = i
   STA   v,X ; v[i] = p+h(p)

9.5.5 Antag att följande deklaration gjorts:
char q;
Dessutom har funktionernachar f1(char) ochchar f2(char) definierats. Vid kodning av följande tilldelningssats där högerledet innehåller två funktionsanrop uppstår registerspill. Visa hur då följande tilldelning kan kodas i FLISP-assembler.
q = f1() + f2();
Anm: -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=?
   JSR   f1    ; A = f1()
   PSHA        ; -(SP) = f1()
   JSR   f2    ; A = f2()
   ADDA  0,SP  ; A = f2() + (SP)
   LEASP 1,SP  ; SP=SP+1
   STA   q     ; q = f1() + f2()

9.5.6 Antag att följande deklarationer gjorts:
char b,c,d,e;
En funktionchar mul( char, char) som returnerar produkten av parametrarna finns också definierad. Visa hur då följande tilldelningar kan kodas i FLISP-assembler. a) b = c * 5; Anm: SP betecknar stackpekarens värde (SP) betecknar innehållet på denna adress -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=?
   LDA   c
   PSHA       ; -(SP) = c
   LDA   #5
   PSHA       ; -(SP) = 5
   JSR   mul  ; A = mul(c,5)
   LEASP 2,SP ; SP = SP+2
   STA   b    ; b = mul(c,5) 
b) b = c * c; Anm: SP betecknar stackpekarens värde (SP) betecknar innehållet på denna adress -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=?
   LDA   c    
   PSHA       ; -(SP) = c
   PSHA       ; -(SP) = c
   JSR   mul  ; A = mul(c,c)
   LEASP 2,SP ; SP = SP+2
   STA   b    ; b = mul(c,c) 
c) b = c * d * e; Anm: SP betecknar stackpekarens värde (SP) betecknar innehållet på denna adress -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=?
   LDA   c
   PSHA       ; -(SP) = c
   LDA   d
   PSHA       ; -(SP) = d
   JSR   mul  ; A = mul(c,d)
   LEASP 2,SP ; SP = SP+2
   PSHA       ; -(SP) = c*d
   LDA   e
   PSHA       ; -(SP) = e
   JSR   mul  ; A = mul(c*d,e)
   LEASP 2,SP ; SP = SP+2
   STA   b    ; b = mul(c*d,e) 

9.5.7 Antag att följande deklarationer gjorts:
char b,c,d,i,j, e[10];
Dessutom har funktionenchar mul( char, char) definierats. Visa hur då följande tilldelning kan kodas i FLISP-assembler.
v[i+j] = b + (c>>2)-d*e[j];
Anm: SP betecknar stackpekarens värde (SP) betecknar innehållet på denna adress -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=? ?=(SP)+ är ett kortare skrivsätt för: ?=(SP);SP=SP+1 &v betecknar adressen till symbolen v
LDA   b
PSHA         ; -(SP) = b
LDA   c      
LSRA         ; A = c>>1
LSRA         ; A = c>>2  
ADDA  0,SP   ; A = b+(c>>2)
LEASP 1,SP   ; SP = SP+1
PSHA         ; -(SP) = b+(c>>2)
LDA   d
PSHA         ; -(SP) = d
LDX   j
LDA   e,X
PSHA         ; -(SP) = e[j]
JSR   mul    ; A = d*e[j]
LEASP 2,SP   ; SP = SP+2
NEGA         ; A = -(d*e[j])
ADDA  0,SP   ; A = b+(c>>2)-(d*e[j])
LEASP 1,SP   ; SP = SP+1
PSHA         ; -(SP) = b+(c>>2)-(d*e[j])
LDA   i      ; A = i
ADDA  j      ; A = i+j
LDX   #v     ; X = &v
LEAX  A,X    ; X = &v+i+j
PULA         ; A = (SP)+
STA   0,X    ; v[i+j] = b+(c>>2)-( d*e[j] )

9.5.8 Antag att följande deklarationer gjorts:
char c,d,e;
En funktionchar mul( char, char) som returnerar produkten av parametrarna finns också definierad. Följande tilldelningssats utförs:
e = mul( c, d );
Visa hur parametrarna refereras i subrutinenmul, dvs. rita stackens utseende och ange speciellt adresser till parametrarna. Anm: SP betecknar stackpekarens värde (SP) betecknar innehållet på denna adress -(SP)=? är ett kortare skrivsätt för: SP=SP-1; (SP)=? Efter anropssekvensen:
   LDA   c 
   PSHA      ; -(SP)=c
   LDA   d
   PSHA      ; -(SP)=d
   JSR   mul ; A=mul(c,d)
får stacken följande utseende: I funktionen mul har därför parameternc adressen 2,SP medan parameternd har adressen 1,SP.


9.6 Lokala variabler och aktiveringsposter

9.6.1 Vi har en funktion:
void f(void)
{
  char lb,lc,ld;
  lb = 1;
  lc = 2;
  ld = 3;
}
a) Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register SP används som pekare till aktiveringsposten. Efter allokering av utrymme för lokala variabler får stacken följande utseende: Funktionen kodas:
f:
   LEASP -3,SP
   LDA   #1
   STA   2,SP   ; lb = 1
   LDA   #2
   STA   1,SP   ; lc = 2
   LDA   #3
   STA   0,SP   ; ld = 3
   LEASP 3,SP
   RTS
b) Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register Y används som pekare till aktiveringsposten. Efter allokering av utrymme för lokala variabler får stacken följande utseende: Funktionen kodas:
f:
   PSHY
   LEASP -3,SP
   TFR   SP,Y
   LDA   #1
   STA   2,Y   ; lb = 1
   LDA   #2
   STA   1,Y   ; lc = 2
   LDA   #3
   STA   0,Y   ; ld = 3
   LEASP 3,SP
   PULY
   RTS

9.6.2 Vi har en funktion:
void f(char param)
{
  char lb,lc;
  lb = 10;
  lc = param;
}
Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register SP används som pekare till aktiveringsposten. Efter allokering av utrymme för lokala variabler får stacken följande utseende: Funktionen kodas:
f:
   LEASP -2,SP
   LDX   #10
   STX   2,SP   ; lb = 10
   STA   1,SP   ; lc = param
   LEASP 2,SP
   RTS

9.6.3 Vi har en funktion:
void f(char param )
{
  char lb,lc,ld;
  lb = 10 * lc;
  lc = param;
}
Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register SP används som pekare till aktiveringsposten. Antag att funktionenmul är definierad sedan tidigare. Eftersom register A (parameter) används vi anropet av subrutinen mul inleds funktionen f med att spilla register A till stacken. Efter allokering av utrymme för lokala variabler får stacken därefter följande utseende: Funktionen kodas:
f:
   PSHA        ; -(SP) = param
   LEASP -3,SP
   LDX   #10
   LDA   1,SP
   PSHX        ; -(SP) = 10
   PSHA        ; -(SP) = lc
   JSR   mul   ; A = mul(10,lc)
   LEASP 2,SP
   STA   2,SP  ; lb = mul(10,lc)
   LDA   3,SP  ; lc = param  
   STA   1,SP
   LEASP 4,SP
   RTS

9.6.4 Funktionen min är definierad i programspråket C enligt:
char min( char b, char c )
{
  if( b < c ) return b;
  return c;
}
a) Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register SP används som pekare till aktiveringsposten. I subrutinen har stacken följande utseende: Funktionen kodas:
min:
   LDA   2,SP
   CMPA  1,SP      ; if(b < c)
   BCS   min_exit  ; return b
   LDA   1,SP      ; return c

min_exit:
   RTS
b) Visa hur funktionen kodas i FLISP-assembler. Redogör speciellt för stackens utseende då register Y används som pekare till aktiveringsposten. Efter allokering av utrymme för lokala variabler får stacken följande utseende: Funktionen kodas:
min:
   PSHY
   TFR   Y,SP
   LDA   3,Y
   CMPA  2,Y      ; if(b < c)
   BCS   min_exit ; return b;
   LDA   2,Y      ; return c;

min_exit:
   PULY
   RTS

9.6.5 Funktionenmin är definierad i programspråket C enligt:
char min( char b, char c, char d )
{
  char tmp;
  if( b < c ) 
    tmp = b;
  else
    tmp = c;

  if( tmp < d ) return tmp;
  return d;
}
Visa stackens utseende i funktionenmin, då register Y används som pekare till aktiveringsposten. Visa också hur funktionen kodas i FLISP-assembler. I subrutinen, efter PROLOG har stacken följande utseende: Funktionen kodas:
min:
   PSHY         ; PROLOG
   LEASP -1,SP
   TFR   Y,SP

   LDA   5,Y		
   CMPA  4,Y    ; if(b < c)
   BLO   min_1
   LDA   4,Y    ; else   
   STA   0,Y    ; tmp = c
   BRA   min_2  

min_1:
   LDA   5,Y
   STA   0,Y    ; tmp = b

min_2:
   LDA   0,Y
   CMPA  3,Y    ; if(tmp < d)
   BLO   min_3
   LDA   3,Y
   BRA   min_4  ; return d
min_3:
   LDA   0,Y    ; return tmp;
min_4:
   LEASP 1,SP   ; EPILOG
   PULY
   RTS

9.6.6 Funktionenmin är definierad i programspråket C enligt:
char min( char v[], char length )
{
  char tmp, i;
  tmp = v[0];
  i = 1;

  while( i < length )
  {
    if ( v[i] < tmp )
      tmp = v[i];
    i = i + 1;
  }
  return tmp;
}
Visa stackens utseende i funktionenmin, då register Y används som pekare till aktiveringsposten. Visa också hur funktionen kodas i FLISP-assembler. I subrutinen, efter PROLOG har stacken följande utseende: Funktionen kodas:
min:
   PSHY         ; PROLOG
   LEASP -2,SP
   TFR   Y,SP

   LDX   5,Y    ; tmp = v[0]
   LDA   0,X
   STA   1,Y
   LDA   #1     ; i = 1;
   STA   0,Y
min_while_continue:
   LDA   0,Y    ; (i < length) ?
   CMPA  4,Y
   BGT   min_while_break
min_while_do:
   LDX   5,Y	; if ( v[i] < tmp )
   LDA   0,Y
   LDA   A,X
   CMPA  1,Y
   BGT   min_1
   STA   1,Y	; tmp = v[i];
min_1:
   INC   0,Y	;i = i + 1;
min_while_break:
   LDA   1,Y	; return tmp;

   LEASP 1,SP   ; EPILOG
   PULY
   RTS


9.7 Kodning i assembler

9.7.1 En 8-bitars strömbrytare, ”DIL-switch” är ansluten till adress FB16 och en displayenhet ”Hexadecimal Display” som visar en byte i form av två hexadecimala siffror är ansluten till adress FC16 i en FLISP dator. En subrutinchar LSBit( char param ) ska ange den minst signifikanta påslagna biten hos parametern genom att returnera dess position, räknat från höger. Om exempelvis bitarna 2 och 4 utgör ettställda strömbrytare ska positionen för bit 2, (dvs. 3) returneras. Om ingen strömbrytare är ettställd ska värdet 0 returneras.
a) Visa subrutinen LSBit, i FLISP assembler. Speciellt gäller att register SP används som pekare till aktiveringsposten.
; Subrutin LSBit
; Register X: En lokal variabel ’position’
; Register A: parameter och returvärde
LSBit:
   LDX   #0      ; position=0
LSBit1:
   TSTA          ;(param==0)?
   BEQ   LSBit2  
   LEAX  1,X
   LSRA          ; param = param >> 1
   BCC   LSBit1  ; if( param!=0)continue
		
LSBit2:
   PSHX          ; return position      
   PULA
   RTS
b) Visa ett huvudprogram, main, som kan användas för att testa subrutinen med FLISP-simulatorn.
   ORG $20
start:
   LDSP  #$20
main:
   LDA   $FB
   BSR   LSBit
   STA   $FC
   BRA   main

LSBit: ...

   ORG   $FF
   FCB   start

9.7.2 Skriv en subrutin CountOnes i assemblerspråk för FLIS-processorn som räknar antalet ettor hos parametern. Subrutinen ska returnera antalet ettor som fanns i registret vid anropet. En funktion i C som motsvarar specifikationen ges av följande och speciellt gäller att register SP ska användas som pekare till aktiveringsposten.
char CountOnes ( char value )
{
   char  count;
   count = 0;
   while( value )
   {
      if( value & 0x80 )
         count = count + 1;
      value = value << 1;
   }
   return count;
}
; Subrutin CountOnes
; Inträde, parameter ’value’ i register A
; Lokal variabel ’count’ på adress 0,SP
; Returvärde i register A
CountOnes:
   LEAS  -1,SP       ; Reservera utrymme för lokal ’count’
   CLR   0,SP        ; count = 0;
CountOnes1:
   TSTA              ; (value ==0 ) ?
   BEQ   CountOnes2  ; om JA, bryt while-slingan
   BITA  #$80        ; (value & 0x80) ? 
   BEQ   CountOnes3
   INC   0,SP        ; count = count + 1
CountOnes3:
   LSLA              ; value = value << 1
   BRA   CountOnes1
CountOnes2:
   LDA   0,SP        ; return count
   LEASP 1,SP
   RTS

9.7.3 Skriv en subrutin AscBin i assemblerspråk för FLIS-processorn som översätter ett 7-bitars ASCII-tecken för en hexadecimal siffra (0-9 eller A-F) till motsvarande binära tal (00000000)2-(00001111)2. Parametern, ASCII-tecknet ges av bitarna b6-b0 medan b7 är en kontrollbit med okänt innehåll och det binära talet ska returneras. Om parametern ej är ASCII-tecknet för en hexadecimal siffra så skall talet FF16 returneras. En funktion i C som motsvarar specifikationen ges av följande:
char AscBin ( char param )
{
   char ascii;
   ascii = param & 0x7F;
   if( ascii < '0' ) return 0xFF;
   if(ascii > 'F' ) return 0xFF;

   if( ascii <= '9' )
      return ( ascii - '0' );
   return( ascii – 'A' + 10 );
}
; Subrutin AscBin
; Register A: parameter, lokal variabel och returvärde
AscBin:
   ANDA  #$7F     ; ascii = param & 0x7F		
   CMPA  #$30     ; if(ascii < '0')
   BCS   ASCERR   
   CMPA  #$46     ; if(ascii > 'F')
   BHI   ASCERR   
   CMPA  #$39     ; if(ascii <= '9')
   BLS   AscBin1  
   ADDA  #10      ; return( ascii + 10 – 'A')
   SUBA  #$41
   BRA   ASCOK    
AscBin1:
   SUBA  #10      ; return( ascii– '0')
   BRA   ASCOK    
ASCERR:
   LDA   #$FF     ; return 0xFF
ASCOK:
   RTS