Vamos ahora a pormenorizar un poco lo que hemos visto anteriormente.
En el ejemplo de las rutinas de gráficos hemos visto como con un código inicial muy pequeño hemos generado un código más grande.
¿Pero que hemos hecho realmente?
lo que hemos hecho es usar la pila como zona de paso de datos, es decir de interface entre la rutina y el programa que la llama. Pero para que no tengamos que estar contando los indices de pila y memorizando que el primero que metimos era el bp, el siguiente la dirección de retorno, el tercero el x, etc hemos usado una estructura.
Para ello vamos a ver otra rutina. En este caso parte de la librería MATH. La rutina de factorial.
Primero la vamos a ve generada con la estructura y luego con la macro rutina.
FAC.ASM (sin apoyarnos en main.mac)
; Copyright (C) 2013 José Ángel Moneo Fernández ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program. If not, see <http://www.gnu.org/licenses/>.;estructura paso de parámetros a través de pila.
_parametros struc
_bp dw ?
_ret dw ?
p1 dw ? ;;primer sumando
p2 dw ? ;;segundo sumando
p3 dw ? ;;resultado
p4 dw ?
p5 dw ?
p6 dw ?
p7 dw ?
p8 dw ?
ends
; codigo
code segment byte public 'code'
assume cs:code,ds:data
public _fac
extrn _mult:near
_fac proc near
push bp
mov bp,sp
push bx
push di
mov bx,[bp].p1 , indexación a través de la estructura para recoger el parametro p1
mov di,[bp].p2
mov word ptr [di],1
mov word ptr [di+2],0
mov word ptr aux,0
mov word ptr aux+2,0
otro:
mov ax,[bx]
cmp aux,ax
jnz no
mov ax,[bx+2]
cmp aux+2,ax
jz fin
no:
add aux,1
adc aux+2,0
push di
push di
mov ax,offset aux
push ax
call _mult
add sp,6
jmp otro
fin:
pop di
pop bx
pop bp
ret
_fac endp
code ends
data segment byte public 'data'
aux dw 0,0
data ends
end
Como se puede apreciar el código está bastante claro al haber usado la estructura, ya que nos ha permitido direccionar fácilmente los datos de intercambio en pila.
Pero ahora vamos a hacer el código usando main.mac y la macro rutina.
FAC.ASM (apoyarnos en main.mac)
; Copyright (C) 2013 José Ángel Moneo Fernández ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program. If not, see <http://www.gnu.org/licenses/>.
; codigo
include main.mac ; incluimos las macros y nuestras propias directivas de compilación
extrn _mult
_modelo exe ;directiva propia para elegir forma de colocar la data en la función
_code ;directiva propia. definición del segmento de codigo
rutina _fac p1,p2 ;directiva propia definición de función con parámetros
push bx
push di
mov bx,[bp].p1 ; indexación a través de la estructura para recoger el parametro p1
mov di,[bp].p2
mov word ptr [di],1
mov word ptr [di+2],0
mov word ptr aux,0
mov word ptr aux+2,0
otro:
mov ax,[bx]
cmp aux,ax
jnz no
mov ax,[bx+2]
cmp aux+2,ax
jz fin
no:
add aux,1
adc aux+2,0
push di
push di
mov ax,offset aux
push ax
call _mult
add sp,6
jmp otro
fin:
pop di
pop bx
pop bp
ret
_fac endp
_data ;directiva propia definición de zona de datos
aux dw 0,0
_end ; directiva propia. Fin de programa. En este caso no damos nombre pues es librería.
Como vemos ha quedado más simple. Igualmente se podría realizar una macro para salvar todos los registros a pila al inicio, pero entonces el código crearía volcados y recuperaciones de registros a pila inútiles. Como lo que queremos con el ensamblador es no crear ni un solo byte innecesario, es mejor sacrificar esa comodidad si implica código basura.
No hay comentarios:
Publicar un comentario
Si tienes algún comentario, duda o sugerencia, o si quieres aportar algún código creado a partir de las librerías expuestas aquí, por favor, indícamelo.