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 |