Quadrato di un numero. Analisi del metodo

Si supponga che la mattonella in figura sia un quadrato di lato 1.

Se si vuole coprire un pavimento quadrato, avente il lato di lunghezza 2, si devono aggiungere altre 3 mattonelle disponendole come quelle gialle in figura:

Continuando ad incrementare la lunghezza del lato del quadrato, per coprire un pavimento quadrato di lato 3 bisogna aggiungere 5 mattonelle, disponendole come quelle verdi in figura:

Da questo esempio si può osservare che il quadrato di un numero N si può ottenere dalla somma dei primi N numeri dispari.

Ad esempio il quadrato Q del numero 4 è ottenuto dalla somma dei primi 4 numeri dispari: 1 + 3 + 5 + 7.

Affinchè il programma funzioni anche nel caso N=0, nella somma si consideri che il primo addendo sia 0, così che il quadrato di 4 si può anche scrivere:

Q = 0 + 1 + 3 + 5 + 7


Algoritmo

Il procedimento di calcolo consiste nell'acquisire in una variabile N il valore del numero da elevare al quadrato. Poi si genera una sequenza dei primi N numeri dispari in una variabile D. Ogni numero dispari viene sommato alla variabile Q, che inizialmente contiene 0.

Le tre variabili individuate vengono memorizzate nei registri interni della CPU. Si decidono le seguenti posizioni:

la variabile ... viene memorizzata nel registro ...
QBX
NCX
DAX

I valori iniziali delle variabili, supponendo di voler calcolare il quadrato di N = 4 sono:

(variabile Q) BX ← 0

(variabile N) CX ← 4

(variabile D) AX ← 1

Con questi valori iniziali si procede al calcolo del quadrato:

OperazioneSimbolivalori in memoria
Si somma a Q il primo numero dispari D e si memorizza il risultato in Q:Q ← Q + D(Q) BX: 1
Si calcola il prossimo numero dispari:D ← D + 2(D) AX: 3
Si contano i dispari che restano da sommare:N ← N - 1(N) CX: 3
Se la quantità di dispari rimasti (N) è 0 allora il procedimento terminaN>0? (Sì)flag Z: falso
Si somma a Q il numero dispari contenuto in DQ ← Q + D(Q) BX: 4
Si calcola il prossimo numero dispari:D ← D + 2(D) AX: 5
Si conta quanti dispari restano da sommare: N ← N - 1(N) CX: 2
Se la quantità di dispari rimasti (N) è 0 il procedimento terminaN>0? (Sì)flag Z: falso
Si somma a Q il numero dispari contenuto in DQ ← Q + D(Q) BX: 9
Si calcola il prossimo numero dispari:D ← D + 2(D) AX: 7
Si conta quanti dispari restano da sommare:N ← N - 1(N) CX: 1
Se la quantità di dispari rimasti (N) è 0 il procedimento terminaN>0? (Sì)flag Z: falso
Si somma a Q il numero dispari contenuto in DQ ← Q + D(Q) BX: 16
Si calcola il prossimo numero dispari:D ← D + 2(D) AX: 9
Si conta quanti dispari restano da sommare:N ← N - 1(N) CX: 0
Se la quantità di dispari rimasti (N) è 0 il procedimento terminaN>0? (Sì)flag Z: vero
Sono stati sommati 4 dispari. Il procedimento è terminato. Il quadrato di N si trova in BX (Q)

Codifica in Assembler

Scrivere il programma in Assembler:

.model small

.data

   Q dw ? ; nella variabile Q si memorizzerà il quadrato di N

   N dw 4 ; calcolare il quadrato di N

.code

inizio:

   MOV AX, @data ; inizializza il registro data segment

   MOV DS, ax

 

   MOV BX, 0 ; Porta Q in BX

   MOV DX, N ; Porta N in DX

   MOV AX, 1 ; Primo numero dispari

 

   MOV CX, DX ; Il registro CX è un contatore

ripeti:

   ADD BX, AX ; somma i numeri dispari

   ADD AX, 0002 ; passa al successivo numero dispari

   DEC CX ; conta una somma

   JCXZ fine ; se il conteggio è giunto a 0 il procedimento termina

   JMP ripeti ; altrimenti si ripete

 

fine:

   mov ax, 4c00h ; uscita dal programma

   int 21h ; si restituisce il controllo al sistema operativo

end inizio ; fine della traduzione. Il punto di inizio del programma è indicato dalla label «inizio».

Salvare il programma con il nome Quadrato.asm

Produrre il file oggetto: tasm quadrato.asm

Produrre il file eseguibile: tlink Quadrato.obj

Avviare il debugger: td Quadrato.exe

Si apre la finestra in cui è in esecuzione il debugger.

Nella finestra si possono riconoscere le seguenti sezioni:

Nel riquadro del codice si osserva l'elenco delle istruzioni:

Indirizzoistruzione macchinaistruzione Asm
cs:0000B8 39 14mov ax, 1439
cs:00038E D8mov ds, ax
cs:0005BB 00 00mov bx, 00
cs:00088B 16 02 00mov dx, [0002]
cs:000CBB 01 00mov ax, 0001
cs:000F8B CAmov cx, dx
cs:001103 D8add bx, ax
cs:001305 02 00add ax, 0002
cs:001649dec cx
cs:0017E3 02jcxz 001B
cs:0019EB F6jmp 001
cs:001BB8 00 4Cmov ax, 4c00
cs:001ECD 21int 21

Analisi del programma con il debugger

Il registro IP punta alla prossima istruzione da eseguire. Tale istruzione è marcata con un triangolino.

I registri della CPU:

AX=0000
BX=0000
CX=0000
DX=0000  
SI=0000
DI=0000
BP=0000
SP=FFEE  
DS=1427
ES=1427
SS=1437
CS=1437
IP=0000

Il registro delle flag:

c=0 (carry)
z=0 (zero)
s=0 (segno)
o=0 (overflow)
p=0 (parità
a=0 (auxiliary carry)
i=1 (interrupt)
d=0 (direzione)

Premendo il tasto F7 si esegue l'istruzione e si può osservare che il puntatore alla prossima istruzione è avanzato e nel registro ax è stato trasferito il valore che si deve assegnare alla base del segmento dati

Dando ripetutamente il comando F7 (Trace) si esegue un'istruzione alla volta e al termine di ciascuna si può osservare lo stato dei registri.

Evitare di eseguire l'istruzione di uscita dal programma (int 21)

Problemi:

  1. Per ripetere l'esecuzione bisogna riportare nel registro IP l'offset della prima istruzione del programma: Cliccare su IP per evidenziarlo, premere il tasto destro su IP e scegliere Change. Scrivere l'offset della prima istruzione e premere invio.

  2. Visualizzare il segmento Dati: View → Dump, Premere il tasto destro sulla finestra Dump e scegliere il comando goto. Inserire l'offset della variabile N. Premendo nuovamente il tasto destro sulla finestra Dump scegliere il comando change. Inserire un nuovo valore da assegnare alla variabile N. Riportare IP all'inizio del programma. Rieseguire il programma passo-passo e verificare la correttezza del risultato.

  3. Modificare un'istruzione: clic sull'istruzione MOV AX, 4C00 per selezionarla. Clic con il tasto destro sull'istruzione selezionata e scegliere il comando Assemble …. Inserire l'istruzione per trasferire il valore contenuto nel registro in cui si trova il valore della radice quadrata di N all'offset della variabile Q. Eseguire il programma passo-passo, dopo aver aggiustato il registro IP, e verificare la correttezza dell'operazione.


Radice quadrata.

Per calcolare la radice quadrata di un numero N si devono contare quanti numeri dispari sono contenuti nel numero N

Per ipotesi il numero di cui si vuole calcolare la radice quadrata è stato memorizzato nel registro AX. Al termine del programma il risultato sarà disponibile nel registro DX.


.model small

.data

   R DW 0

   N DW 19

.code

inizio:

   MOV AX, @data

   MOV DS, AX

 

   MOV AX, N

   MOV DX, 1

   MOV CX, 1

ripeti:

   SUB AX, CX

   JL fine

   INC DX

   ADD CX, 2h

   JMP ripeti

fine:

   MOV AX, 4C00h

   int 21h

end inizio

Assemblare e linkare il programma. Avviare il debugger

La radice quadrata del numero inizialmente contenuto in AX è disponibile in DX.

Verificare il programma passo passo

Prima di eseguire il programma una seconda volta bisogna porre il contenuto del registro IP a valore 0, l'indirizzo della prima istruzione del programma.

Quesiti:

L'istruzione all'offset 0010 è jl 0018 (jump if less to 0018) significa che se l'operazione aritmetica precedente ha dato risultato minore di zero (nell'istruzione il confronto con 0 è sottinteso) bisogna proseguire con l'esecuzione del programma a partire dall'istruzione all'offset 0112 altrimenti bisogna continuare con l'istruzione successiva. Quando il risultato è minore di zero quali flag vengono modificate?

Calcolare il valore rappresentato dal codice binario contenuto in AX.

Esercizi:

Memorizzare il risultato nella variabile R