lunes, 26 de marzo de 2012

Ensamblador 8086 atoi

Para implementar la tarea donde tuvimos que leer del usuario dos números enteros, realizar operaciones con ellos y desplegar el resultado, fue necesario implementar dos rutinas muy interesantes: itoa (para convertir un entero a cadena) y atoi (para convertir una cadena a entero). Los nombres de estas dos rutinas los tomé de las funciones en C que ayudan a realizar estás tareas, entero a cadena (integer to ascii por sus siglas en inglés) y cadena a entero (ascii to integer). En este post analizaremos la implementación de atoi.

El objetivo de esta función es tomar una cadena y convertirla a su valor entero. Por ejemplo la cadena “120” debe generar el entero 120. El pseudo-código para esta función es el siguiente:

1 entero = 0
2 temp = 0
3 indice = 0
4 while cadena[indice] es un digito
5   temp = convertir cadena[indice] a digito
6   entero = entero * 10
7   entero = entero + temp
8   indice = indice + 1
9 end while

Recuerden que en ascii los caracteres '0' al '9' se encuentran de manera consecutiva, de hecho el valor númerico de '0' es 30h y el de '9' es 39h. Por lo que el paso 4 del código anterior se puede implementar fácilmente verificando si cadena[indice] se encuentra entre '0' y '9'. De la misma forma, en el paso 5, sólo basta con restar el valor de '0' a cadena[indice] para obtener el valor del dígito en esa posición. El siguiente post muestra el código en ensamblador para esta función (sólo tuve que cambiar los registros de 32 a 16 bits, por ejemplo de eax a ax).

La siguiente función muestra la versión de 16 bits de atoi, la cadena a convertir debe iniciar en DS:SI y el valor final lo regresa en BX.

; ========= Convertir cadena a numero ===========
; Parametros
; si: offset inicial de la cadena con respecto a DS
; Retorna
; bx: valor
atoi proc
  xor bx,bx   ;BX = 0

atoi_1:
  lodsb       ;carga byte apuntado por SI en AL
              ;e incrementa si
  cmp al,'0'  ;es numero ascii? [0-9]
  jb noascii  ;no, salir
  cmp al,'9'
  ja noascii  ;no, salir

  sub al,30h  ;ascii '0'=30h, ascii '1'=31h...etc.
  cbw         ;byte a word
  push ax
  mov ax,bx   ;BX tendra el valor final
  mov cx,10
  mul cx      ;AX=AX*10
  mov bx,ax
  pop ax
  add bx,ax
  jmp atoi_1  ;seguir mientras SI apunte a un numero ascii
  noascii:
  ret         ;BX tiene el valor final
atoi endp

No hay comentarios:

Publicar un comentario