Saltar al contenido

Suma de polinomios con código ensamblador x86-64

Sumar polinomios en lenguaje ensamblador

Esta semana he estado haciendo una pr√°ctica de ensamblador, consistia en sumar dos polinomios desde ensamblador pas √°ndole los par√°metros desde C a ensamblador.

Primero definiremos la pr√°ctica para entender mejor el c√≥digo. Tenemos dos polinomios de exponentes siempre positivos, y en este caso no m√°s grandes de 20 t√©rminos, aunque esto es lo de menos se puede modificar facilmente en el c√≥digo y adaptarlo al tama√Īo del polinomio que necesitemos.

Cada polinomio est√° formado por dos vectores uno tendr√° el indice del coeficiente y otro el indice del exponente.

Por ejemplo así:

1
2
3
4
 int p_coef[20]={-16,+10,+18,+2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 //coeficientes del polinomio P
  int p_exp [20]={+15,+ 9,+ 5,+1,+0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
//exponentes del polinomio P

Sería igual a este: -16*x^15 +10*x^9 +18*x^5 +2*x^1 -1*x^0

Los terminos ‚Äúvacios‚ÄĚ en el polinomio los hemos dejado como 0 ^-1, por lo tanto hemos rellenado las posiciones sin terminos con 0^1 hasta 20 que es el tama√Īo que hemos definido para el polinomio.

Si realizamos la suma de los dos polinomios p y q que tenemos declarados en el código obtendremos este resultado.

+1*x^10 -8*x^9 +5*x^8 +12*x^7

-16*x^15 +10*x^9 +18*x^5 +2*x^1 -1*x^0

————————————— ———————————————-
-16*x^15 +1*x^10 +2*x^9 +5*x^8 +12*x^7 +18*x^5 +2*x^1 -1*x^0

Segundo, ahora comentaremos como funciona el código. Para empezar declaramos en C los polinomios y creamos una función que mostrará el polinomio por pantalla.

1
2
3
4
5
6
7
8
9
10
  int p_coef[20]={-16,+10,+18,+2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
   //coeficientes del polinomio P
  int p_exp [20]={+15,+ 9,+ 5,+1,+0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
   //exponentes del polinomio P
 
  int q_coef[20]={+0,+0,+0,+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  int q_exp [20]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
 
  int r_coef[20]={ +1,-8,+5,+12,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  int r_exp [20]={+10,+9,+8, +7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};

Función que mostrará el polinomio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void p_print(int v_coef[], int v_exp[]){  
 
  if (v_exp[0]==-1) {
    printf ("Polinomi sense termes \n\n");
  }
  else {
    int i=0;
    while (v_exp[i]!=-1 && i<20) {
      if (v_coef[i]>=0) printf (" +"); else printf (" ");
      printf("%d*x^%d ",v_coef[i], v_exp[i]);
      i++;
    }
    printf("\n\n");
  }
}

Y por √ļltimo llamamos al c√≥digo escrito en ensamblador pas√°ndole los parametros que queremos:

suma_ensamblador(r_coef,r_exp,p_coef,p_exp,q_coef,q_exp);

Es importante el orden en el que los ponemos, pues al c√≥digo ensamblador le llegar√° el primer parametro a traves del registro rdi, el segundo llegar√° a rsi, y sucesivamente llegar√°n a rdx, rcx, r8 y por √ļltimo r9.

Este es el código completo con comentarios escrito en C:

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
#include <stdio.h>
 
 
/** la función que mostrará el polinomio   **/
 
void p_print(int v_coef[], int v_exp[]){  
 
  if (v_exp[0]==-1) {
    printf ("Polinomi sense termes \n\n");
  }
  else {
    int i=0;
    while (v_exp[i]!=-1 && i<20) {
      if (v_coef[i]>=0) printf (" +"); else printf (" ");
      printf("%d*x^%d ",v_coef[i], v_exp[i]);
      i++;
    }
    printf("\n\n");
  }
}
 
 
int main() {  
/**
 * Programa Principal
*/
 
  int p_coef[20]={-16,+10,+18,+2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  //coeficientes del polinomio P
  int p_exp [20]={+15,+ 9,+ 5,+1,+0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
  //exponentes del polinomio P
 
  int q_coef[20]={+0,+0,+0,+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  int q_exp [20]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 
 
  int r_coef[20]={ +1,-8,+5,+12,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  int r_exp [20]={+10,+9,+8, +7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
 
 
  printf("Polinomio p(x)\n");
  p_print(p_coef, p_exp);
  printf("Polinomio q(x)\n");
  p_print(q_coef, q_exp);
 
 
  printf("******************************************\n");
 
  p_print(r_coef, r_exp);
  p_print(p_coef, p_exp);
 
  printf("---------------------------------------*\n");
  suma_ensamblador(r_coef,r_exp,p_coef,p_exp,q_coef,q_exp);
  p_print(q_coef, q_exp);
 
 
}

Este es el código comentado escrito en ensamblador para la arquitectura de 64bits (x86-64):

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
section .data             
 
 
section .text                
 
  ; declaramos las subrutinas que queremos hacer visibles desde C                         
  global suma_ensamblador
 
 
 
 
 
; Sumaos dos polinomios. t(x)=r(x)+s(x)
 
; Paràmetres d'entrada : r_coef(rdi), r_exp(rsi),
;                        s_coef(rdx), s_exp(rcx),
;                        t_coef(r8 ), t_exp(r9 )    
 
suma_ensamblador:
 
 
  push rbp
  mov  rbp, rsp
  push rbx
  push r10
  push r11     ; guardamos los valores que queremos dejar intactos.
  push r12
  push r13
  push r14
 
  mov rax,-1
  mov r11,0 
  mov r10,0  ; para comparar  
 
  mov rbx,0  ;numero total de elementos en el polinomio
 
  mov r12,0  ;r
  mov r13,0  ;s
  mov r14,0  ;t
 
; r_coef(rdi), r_exp(rsi),
; s_coef(rdx), s_exp(rcx),
; t_coef(r8 ), t_exp(r9 )    
 
  inicio:
  cmp rbx,20
  je finalmal
 
  mov r10d,dword[rsi+r12*4]    ;exp r
  mov r11d,dword[rcx+r13*4]    ;exp s
 
 
  cmp r10d,r11d                ;comparamos los exponentes r y s
  jl r_menor
  je equals
 
 
  ; caso de que sea mayor r q s
  mov [r9+r14*4],r10d  ;movemos el exponente
 
  mov r10d, dword[rdi+r12*4] ;movemos el coeficiente
  mov [r8+r14*4],r10d
 
  inc rbx  ;numero total de elementos en el polinomio
 
  inc r12  ;r
  inc r14  ;t
 
  jmp inicio
 
  r_menor:
 
  mov [r9+r14*4],r11d  ;movemos el exponente
 
  mov r11d, dword[rdx+r13*4] ;movemos el coeficiente
  mov [r8+r14*4],r11d
 
  inc rbx  ;numero total de elementos en el polinomio
 
  inc r13  ;s
  inc r14  ;t
 
  jmp inicio
 
  equals:
  cmp r10d,-1
  je finalbien
 
  mov [r9+r14*4],r11d  ;movemos el exponente
 
  mov r11d, dword[rdx+r13*4] ;movemos el coeficiente de s
  mov [r8+r14*4],r11d
 
  mov r11d, dword[rdi+r12*4] ;movemos el coeficiente de r
  add [r8+r14*4],r11d        ;sumamos el coefciente de r a s
 
  inc rbx  ;numero total de elementos en el polinomio
  inc r12  ;r
  inc r13  ;s
  inc r14  ;t
 
  jmp inicio
 
  finalbien:
  mov rax,0
 
  finalmal:
 
  pop r14
  pop r13
  pop r12
  pop r11
  pop r10
  pop rbx
  mov rsp, rbp
  pop rbp
  ret

Entradas relacionadas

Deja una respuesta

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

Comentarios (2)

Buenas, he estudiado los registros del cpu, los direccionamientos y como tambien las interrupciones(se que se inicia con .model small, .data y .code pero que m√°s).
Me ense√Īar√≠a hacer el codigo para sumar dos numeros decimales en ensamblador, por favor.
Gracias

Responder

Hola hahrukh.com,
Tienes alg√ļn ejemplo dentro de la web, no son con n√ļmeros decimales sino n√ļmeros enteros, pero creo que se puede adaptar f√°cilmente.
Un saludo,

Responder