Saltar al contenido
Codifíca.me | Desarrollo web | Programación

Programar en lenguaje ensamblador | Ejemplo Práctico

11 junio, 2012

Lenguaje ensamblador

En esta práctica realizamos el desarrollo de un programa en código en lenguaje ensamblador y nos ayudamos del código C para realizar algunas operaciones como mostrar los resultados por pantalla, declarar los valores de los polinomios o definir la estructura principal dónde podemos elegir que tarea realizaremos con el polinomio.

La práctica trata de desarrollar un conjunto de operaciones matemáticas con polinomios, estas son las operaciones que vamos a desarrollar en lenguaje ensamblador:

– Ordenar los términos de un polinomio.
– Evaluar un polinomio.
– Grado de un polinomio.
– Hacer la derivada de un polinomio.
– Hacer la integral de un polinomio.
– Sumar dos polinomios.

El código C hará lo siguiente:

Mostrará un menú por pantalla con las opciones que tiene:

1. Ordenar los términos de un polinomio.
2. Evaluar un polinomio.
3. Grado de un polinomio.
4. Hacer la derivada de un polinomio.
5. Hacer la integral de un polinomio.
6. Sumar dos polinomios.

Y dependiendo del valor que leamos realizaremos las siguientes funciones (en pseudocódigo):

Leemos el valor
if valor=1 //Ordenaremos el polinomio r
Muestra el polinomio r(x)
m_pol_bubbleSort(); //subrutina en ensamblador
Muestra el polinomio r(x)
end if
if valor=2 //Evaluaremos el polinomio. y = p(x)
Muestra el polinomio p(x)
Leer valor escalar
y = p_pol_eval(); //subrutina de evaluación en ensamblador
Muestra ‘y’, valor obtenido de evaluar p(x=escalar).
end if
if valor=3 //Sumar dos polinomios. r(x)=p(x)+q(x)
Muestra los polinomios p(x) i q(x).
p_pol_add(); //subrutina en ensamblador
Muestra el polinomio resultado, r(x)
end if
if valor=4 //Hacer la derivada de un polinomio. r(x)= p'(x)
Muestra el polinomio p(x)
p_pol_derive(); //subrutina en ensamblador
Muestra el polinomio resultado, r(x)
end if
if valor=5 //Realizar la integral de un polinomio. r(x)= Integral (q(x))
Muestra el polinomio p(x)
p_pol_integrate(); //función en C
Muestra el polinomio resultado, r(x)
end if

El código en lenguaje ensamblador tiene que implementar las subrutinas siguientes:

p_delete:
Borrar el polinomio. Poniendo los valores del coeficiente a 0 y el exponente a -1.

p_bubbleSort:
Ordenar el polinomio r(x) utilizando el algoritmo de la burbuja.

p_pow:
Realizar la potencia de un término, que luego utilizaremos para evaluar el polinomio

p_eval:
Evaluaremos un polinomio utilizando la subrutina p_pow para cada término y sumando el total de los términos.

p_add:
Sumamos dos polinomios, si el polinomio resultante es superior a 20 no lo sumaremos y mostraremos por pantalla la imposibilidad de sumarlo por ser superior al espacio que tenemos reservado.

p_derive:
Realizaremos la derivada de un polinomio.

Este es el código C comentado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdio.h>
 
//polinomio p(x) = -16x^15 +10x^9 +18x^5 +2x -1
int p_coef[20]={-16,+10,+18,+2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
//Vector con los coeficientes
int p_exp [20]={+15,+ 9,+ 5,+1,+0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
//Vector con los exponentes
//polinomio q(x) = 11x^10 -12x^5 +4x^3 -2x
int q_coef[20]={+11,-12,+4,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
//Vector con los coeficientes
int q_exp [20]={+10, +5,+3,+1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
//Vector con los exponentes
//polinomio r(x) = x^10 -8x +5x^2 +12x^7 -3 +x^18 -5x^17
int r_coef[20]={ +1,-8,+5,+12,-3, +1, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 //Vector con los coeficientes
int r_exp [20]={+10,+1,+2, +7,+0,+18,+17,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
//Vector con los exponentes
 
int x;        
int y;        
int e;       
 
 
/**
 * 
 * Funcions de la P1
 * 
*/
 
/**
 *  Función que borra el  polinomio v. Dejando los Coeficientes a 0 y los exponentes a -1.
 */
void p_deleteC(int v_coef[], int v_exp[]) {
 int i;
  for (i=0; i<20; i++) {
    v_coef[i]= +0;
    v_exp[i] = -1;
  }
}
 
/**
 *  Pinta por pantalla el polinomio, si todos los terminos tienen exponente a -1 
 *  mostrará la frase "Polinomio sin términos"
 */
 
void p_print(int v_coef[], int v_exp[]){  
 
  if (v_exp[0]==-1) {
    printf ("Polinomio sin términos \n\n");
  }
  else {
    int i=0;
    while (i<=20) {
      if (v_coef[i]!=0) {
	if (v_coef[i]>=-1) printf (" +"); else printf (" ");
	printf("%dx^%d",v_coef[i], v_exp[i]);
      }
      i++;     
    }
    printf("\n\n");
  }
}
 
/**
 *  Realiza la integral del polinomio q(x).  r(x)=Integral[q(x)].
 *  Borra el polinomio r(x) antes de hacer la integral utilizando la función p_deleteC().
 */
 
void p_integrate(){  
    p_deleteC(r_coef, r_exp);
    int i=0;
    while (q_coef[i]!=0 && i<20) {
      r_coef[i]=(q_coef[i]/(q_exp[i]+1));
      r_exp[i]=q_exp[i]+1;    
      i++;
    }
}
 
 
int main() {  
  /**
   * Programa Principal de la P1
  */
 
  int op=1; 
  /** pinto el polinomio **/
 
 
  while(op!=0){
  printf("\n");
  printf("1 - Ordenar els termes d'un polinomi\n");
	printf("2 - Avaluar un polinomi\n");
	printf("3 - Sumar dos polinomis\n");
	printf("4 - Fer la derivada d'un polinomi\n");
	printf("5 - Fer la integral d'un polinomi\n");
	printf("Opció: ");
	scanf("%d",&op);
 
 
	switch(op){
		case 1: //Ordena los terminos del polinomio
			 p_print(r_coef, r_exp);		
			 p_bubbleSort(); //subrutina en ensamblador
			 p_print(r_coef, r_exp);
			 break;
		case 2: //Evalua un polinomio. y=p(x)                  
			 p_print(p_coef, p_exp);		
			 printf("Número para evaluar el polinomio: ");
			 scanf("%d",&x);                        
			 y = p_eval();			
			 printf("Resultado: %d", y);
			 break;
		case 3: //Sumar dos polinomis. r(x)=p(x)+q(x)4			
			p_print(p_coef, p_exp);		
			p_print(q_coef, q_exp);		
			y = p_add();						
			printf("Resultado: %d \n" , y);			
			p_print(r_coef, r_exp);			
			break;	
 
		case 4:  //Realiza la la derivada de un polinomio. r(x)= p'(x)
			p_print(p_coef, p_exp);
			p_derive();
			p_print(r_coef, r_exp);
			break;
 
		case 5:  //Realiza la integral de un polinomio. r(x)= Integral (q(x))			
			p_print(q_coef, q_exp);
			p_integrate(q_coef,q_exp);
			p_print(r_coef, r_exp);
			break;
	}
   }  
}

Este es el código Ensamblador .asm comentado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
 
section .data          
section .text               
 
  ;hace que sean visibles desde C las subrutines de ensamblador siguientes:
 
  global p_delete, p_bubbleSort, p_eval, p_degree, p_add, p_derive
 
  ;hace que sean visibles en ensamblador las siguientes variables definidas en C.
 
  extern p_coef, p_exp, q_coef, q_exp, r_coef, r_exp, x        
 
 
 
;****************************************************************************************
;*                            función p_delete
;*               Parametros de entrada : vec_coeficients(rax), vec_exponents(rbx)
;*               Parametros de salida: ninguno
;****************************************************************************************
 
p_delete:
 
  push rbp
  mov  rbp, rsp
  push rcx
                   ;Los parámetros se pasan a través de los registros RDI,RSI,RDX,RCX,R8 y R9. 
                   ;Si hay más de 6 parámetros, el resto se pasan mediante la pila. 
                   ;Como esta función solo tiene 2 parámetros, solo hace falta 
                   ;leer los registros RDI y RSI.
 
  mov ecx,19  ; Utilizo otro registro como contador
 
  p_delete_loop:    
   mov dword[eax+ecx*4],0     ; RDI es el primer parámetro que es r_coef
   mov dword[ebx+ecx*4],-1    ; RSI es el 2º parámetro que es r_expf
   dec ecx
   jge p_delete_loop
 
  p_delete_end:
 
;Como en el código C asigno el resultado de la función a una variable
; este resultado se devuelve en RAX.
; En este caso, se devuelve un -1
  pop rcx
  mov rsp, rbp
  pop rbp
 
  ret
 
 
 
 
;****************************************************************************************
;*                            Algoritmo de la burbuja para polinomios
;*                              Sin parametros de entrada
;*                              Sin parametros de entrada
;**************************************************************************************** 
 
p_bubbleSort:
 
  push rbp
  mov  rbp, rsp
  push rax          ;guardamos ena la pila los registros que vamos a modificar
  push rbx                  
  push rcx
  push rdx
  push rsi
  push rdi
 
  mov  esi, 0                ;inicializo el indice
  mov  edi, 0
 
 
  mov  ebx, r_exp              ;vector que ordenar 
  mov  eax, r_coef
 
  p_bubble_sort_loop1:
    mov edx, [ebx+esi*4]
    mov ecx, [eax+esi*4]
 
    mov edi, esi
    inc edi                  
    p_bubble_sort_loop2:
      cmp [ebx+edi*4], edx
      jle p_bubble_sort_no_xchg
 
        p_bubble_sort_xchg:
        xchg edx, [ebx+edi*4] ;exponente
        xchg ecx, [eax+edi*4] ;numero
      p_bubble_sort_no_xchg:
      inc edi
      cmp edi,20
      jl  p_bubble_sort_loop2 
 
    mov [ebx+esi*4],edx
    mov [eax+esi*4],ecx 
    inc esi
    cmp esi, 19
    jl  p_bubble_sort_loop1
 
  p_bubble_sort_end:
  pop rdi              ;devolvemos el valor original a 
  pop rsi
  pop rdx              ;los registros que hemos modificado
  pop rcx
  pop rbx
  pop rax
  mov rsp, rbp
  pop rbp
  ret
 
 
 
 
;****************************************************************************************
;*                       Calcular la potencia
;*               Parametros de entrada :  base(rbx), exponent(rcx)
;*               Parametros de salida:  rax (pow = b^e)
;**************************************************************************************** 
 
 
p_pow:
  push rbp
  mov  rbp, rsp
  push rdi
 
  mov edi,1
 
  cmp ecx,0
  jne smul
  mov eax,1 ;el resultado sería 1 y saldríamos del subprograma
  jmp fin
 
smul: 
  imul ebx,edi
 
  mov eax,ebx
  cmp edi,1
  je unciclo
 
sigue:
  dec ecx
  jne smul
  je fin
 
unciclo:
  mov edi,ebx 
  jmp sigue
 
fin: 
 
 
  pop rdi
  mov rsp, rbp
  pop rbp
  ret
 
 
 
;*********************************************************************************
;*                Evaluar un polinomio para un valor x
;*        p_eval    Con registros EAX, EBX, ECX, EDX, ESI, EDI
;*               Parametros de entrada: Cap
;*               Parametros de salida: rax 
;*
;**********************************************************************************
 
p_eval: 
  push rbp
  mov  rbp, rsp
  push rbx
  push rcx  
  push rdi
  push rsi
 
  mov edi,0   ;inicializo edi
  mov esi,0    ;inicializo r8
 
  iniciobucle:
 
   cmp edi,19
   je fin_bucle
   mov ebx,[x]
   mov ecx,dword[p_exp +edi*4]
   ;mov dword[rbx],edi
   cmp ecx,-1
   je expNeg      ; exponente con -1
 
   call p_pow   
 
   imul eax,dword[p_coef+edi*4]   ;multiplica el número por el valor de X
 
             ;Los parámetros se pasan a través de los registros RDI,RSI,RDX,RCX,R8 y R9. 
   add esi,eax
 
 expNeg:
 
 inc edi
 jmp iniciobucle
 
 fin_bucle:
  mov eax,esi  ;obtengo el valor de todas las sumas de todas las multiplicaciones en rax
 
  pop rsi
  pop rdi 
  pop rcx
  pop rbx
  mov rsp, rbp
  pop rbp
  ret
 
 
 
 
;*********************************************************************************
;*
;*        p_add    Con registros EAX, EBX, ECX, EDX, ESI, EDI
;*                   Sumar dos polinomios. r(x)=p(x)+q(x)
;*                   Parametros de entrada : Cap
;*                   Parametros de salida: rax 
;*
;**********************************************************************************
 
 
   p_add:
 
  push rbp
  mov  rbp, rsp
  push rdi
  push rsi
  push rdx
  push rcx
  push r9
  push r12
  push r13
  push r14
  push rax 
  push rbx
 
 
    mov rax,r_coef        
    mov rbx,r_exp
 
 
    call p_delete
 
 
    mov r9, 0   ;int i 
    mov r12, 0  ;int j = 0;
    mov r13, 0  ;int k = 0;
    mov r14, 0  ;int numberOfTerms = 0;    
 
 
 
 
   comienzafor:
      mov edi,0  ;suma_terminos  
      cmp r9,20   ;cc19      
      je saldelfor
 
 
 
     mov edx,dword[p_exp +r12*4]    
     mov ecx,dword[q_exp +r13*4] 
     cmp edx,ecx 
 
   je sumaterminos
   jg elseifmasgrande 
   jl elseifmaspeque
   siguefor1:
 
   sumaterminos:
         mov edx,dword[p_coef +r12*4]    
         mov ecx,dword[q_coef +r13*4] 
       add edi,edx
       add edi,ecx         
 
       cmp edi,0
 
       jne cambioexp    
       je sincambioexp  
 
   cambioexp:
       mov esi,dword[p_exp+r12*4]   ;utilizo esi para mover los datos
       mov dword[r_exp+r9*4],esi    ;r_exp[i] = p_exp[j];
 
       mov dword[r_coef+r9*4],edi  ;r_coef[i] = sum_coef
 
       inc r14                  ;numberOfTerms++
   sincambioexp:
         inc r12               ;j++
         inc r13               ;k++
         jmp totalterminos
   elseifmasgrande:
           mov esi,dword[p_exp+r12*4]    ;utilizo esi para mover los datos
           mov dword[r_exp+r9*4],esi    ;r_exp[i] = p_exp[j];  
 
           mov esi,dword[p_coef+r12*4]   ;mov r_coef[i] = p_coef[j]
           mov dword[r_coef+r9*4],esi
 
         inc r12               ;j++
         inc r14               ;numberOfTerms++
         jmp totalterminos
 
   elseifmaspeque:
            mov esi,dword[q_exp+r13*4]
            mov dword[r_exp+r9*4],esi       ;r_exp[i] = q_exp[k]
 
            mov esi,dword[q_coef+r13*4]
            mov dword[r_coef+r9*4],esi      ;r_coef[i] = q_coef[k]
            inc r13                     ;k++
            inc r14                     ;numberOfTerms++       
 
         jmp totalterminos        
   totalterminos: 
           inc r9
           cmp r14,20      ;numberOfTerms > 20) {
           jle comienzafor 
                           ;p_deleteC(r_coef, r_exp);
      ;     mov rax,r_coef  ; 
      ;     mov rbx,r_exp
 
           call p_delete
 
           mov eax,-1                        
           jmp finfor       
 
   saldelfor:
 ;  mov [r_coef],eax
 ;  mov [r_exp],ebx
   mov eax,0   ;final y pone el return a 0
 
finfor:
 
 
  pop rbx
  pop rax 
  pop r14
  pop r13 
  pop r12   
  pop r9  
  pop rcx
  pop rdx
  pop rsi
  pop rdi
  mov rsp, rbp
  pop rbp
  ret
 
 
 
;*********************************************************************************
;*               Realizar la derivada de un polinomio
;*            Con registros EAX, EBX, ECX, EDX, ESI, EDI
;*                Parametros de entrada : Cap
;*                Parametros de salida: Cap
;*
;**********************************************************************************
 
p_derive:
  push rbp
  mov  rbp, rsp
  push rax
  push rbx
  push rsi
  push rdi
  push rcx
 
  mov rax, r_coef  ;rdi,r_coef  escribo la posición de memoria donde empieza el polinomio R.
  mov rbx, r_exp  ;mov rsi,r_exp  escribo la posición de memoria donde empieza el exponente R.
 
  call p_delete    ; borro el polinomio.
  ;El vostre codi
 
    mov rcx,19  ; Utilizo otro registro como contador
 
  p_for_loop:    
   mov esi,dword[p_coef+rcx*4]   ;escribo la posición de memoria donde empieza el polinomio P.
   mov edi,dword[p_exp +rcx*4]   ;escribo la posición de memoria donde empieza el exponente P.
 
   imul esi,edi
   dec edi
 
   mov [eax+ecx*4],esi     ; RDI es el primer parámetro que es r_coef
   mov [ebx+ecx*4],edi    ; RSI es el 2º parámetro que es r_expf               
   dec rcx
   jge p_for_loop
 
  p_for_end:
 
 
  pop rcx  
  pop rdi
  pop rsi
  pop rbx
  pop rax
  mov rsp, rbp
  pop rbp
  ret

Entradas relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Comentarios (4)

Hola,
quisiera saber como cuento los numeros pares en una matriz en el lenguaje ensamblador, y como imprimo el numero mayor de cada fila en la matriz !!

Responder

Hola Sahil,
Tienes ejemplos de código ensamblador dónde se muestra por pantalla el valor de algunas variables, seguramente te valga.
Un saludo.

Responder

Hola,
Estoy estudianto Tecnología de sistemas.
Tengo clases de Lenguaje ensamblador que me han llamado mucho la atención.
Gracias por los artículos

Responder

Hola Jeffer21,
La verdad que programar en ensamblador fue una de las asignaturas que más me gustó de la carrera. Interesante para aprender a programar y para ver como funciona el espacio de memoria, variables, etc.
Actualmente con los entornos de desarrollo que existen se puede programar perfectamente sin conocer nada de esto, pero a mi entender es bastante interesante aprender a programar en ensamblador.
Un saludo.

Responder