Programación en ensamblador: entorno Turbo Assembler y Turbo Debugger Para realizar un programa que se ejecute en un PC, hay que partir de un fichero fuente en ensamblador, escrito con un editor de texto, que genere códigos ASCII, tal como block de notas. El programa fuente que a continuación se lista se denomina FACTOR.ASM. ;******************************************************************************* ;******************************************************* ************************ ; CALCULA EL PRODUCTO DEL FACTORIAL DE DOS NUMEROS QUE SE ; ENCUENTRAN EN LAS POSICIONES DE MEMORIA 0 Y 1 DEL SEGMENTO DE ; DATOS. EL VALOR DE C ADA NUMERO DEBE SER INFERIOR A 9. EL RESULTADO ; SE ALMACENA EN DOS PALABRAS DEL SEGMENTO EXTRA, EN LA PRIMERA ; PALABRA EL MENOS SIGNIFICATIVO Y EN LA SEGUNDA EL MAS ; SIGNIFICATIVO. SE UTILIZA UNA RUTINA PARA CALCULAR EL FACTORIAL. ;_______________________________________________________________________ ; DEFINICION DEL SEGMENTO DE DATOS DATOS SEGMENT DATO_1 DATO_2
DB DB
0 0
DATOS ENDS ;_______________________________________________________________________ ; DEFINICION DEL SEGMENTO DE PILA PILA
SEGMENT STACK "STACK" DB 40H DUP (0) PILA ENDS ;_______________________________________________________________________ ; DEFINICION DEL SEGMENTO EXTRA EXTRA
SEGMENT RESULT DW 0,0 ; 2 PALABRAS ( 4 BYTES ) EXTRA ENDS ;_______________________________________________________________________ ; DEFINICION DEL SEGMENTO DE CODIGO
CODE
SEGMENT ASSUME CS:CODE, DS:DATOS, ES: EXTRA, SS:PILA
FACT_DATO_1 DW
0
; COMIENZO DEL P ROCEDIMIENTO PRINCIPAL START PROC ;INICIALIZA LOS REGISTROS DE SEGMENTO CON SUS VALORES MOV AX, DATOS MOV DS, AX MOV AX, PILA MOV SS, AX MOV AX, EXTRA MOV ES, AX ; CARGA EL PUNTERO DE PILA CON EL VALOR MAS ALTO
MOV SP, 64 ; FIN DE LAS INICIALIZACIONES ;COMIENZO DEL PROGRAMA MOV CL, DATO_1 CALL FACTOR MOV FACT_DATO_1, AX ; ALMACENA EL RESULTADO MOV CL, DATO_2 CALL FACTOR MOV BX, FACT_DATO_1 MUL BX ; EN AX ESTA EL RESULTADO DEL FACTORIAL DEL SEGUNDO ; ALMACENA EL RESULTADO MOV RESULT, AX MOV RESULT+2, DX ; FIN DEL PROGRAMA MOV AX, 4C00H INT 21H START ENDP ;_______________________________________________________________ ; SUBRUTINA PARA CALCULAR EL FACTORIAL DE UN NUMERO ; ENTRADA CL=NUMERO ; SALIDA AX=RESULTADO, DX=0 YA QUE CL<=9 ;_______________________________________________________________ FACTOR PROC NEAR MOV AX, 1 XOR CH,CH CMP CX, 0 JE FIN IR: MUL CX DEC CX JNE IR FIN: RET FACTOR ENDP ; FIN DEL SEGMENTO DE CODIGO CODE ENDS ; FIN DEL PROGRAMA INDICANDO DONDE COMIENZA LA EJECUCION END START ;_______________________________________________________________________ En el programa fuente anterior es importante destacar: * El orden en que aparecen los diferentes segmentos (datos, código, pila) dentro del programa fuente es indiferente. Alguno puede no aparecer. El segmento de pila debe aparecer si se utilizan instrucciones que la usan, si se utilizan recursos del sistema o si se piensa hacer "debug". En general, todos los programas necesitan una pila con un tamaño mínimo de 64 bytes. * Al definir el comienzo del segmento de pila hay que escribir: SEGMENT STACK "STACK" * Al comienzo del segmento de código hay que utilizar la directiva ASSUME para relacionar el nombre dado a los segmentos con el registro de segmento a través del cual van a ser accedidas las posiciones de memoria existentes en cada segmento. Sin embargo esta directiva no carga el valor de los registros de segmento (DS, SS, ES) con los valores asignados a los segmentos. Las instrucciones que cargan estos valores deben ser las primeras de cualquier programa.
* Las instrucciones sólo pueden existir en el segmento de código. Sin embargo, los dato s pueden estar en cualquier segmento. La situación más usual es que aparezcan todos en el segmento de datos. * Para finalizar el programa es necesario utilizar la interrupción INT 21H con AX=4C00h, que devuelve el control al DOS. * La última línea debe tener la directiva END seguida por el nombre del procedimiento donde empieza a ejecutarse el programa.
Para poder ensamblar el programa hay que tener el path dirigido a c:\tasm;c:\td y escribir c:\> TASM /zi factor donde factor es el nombre del programa fuente a ensamblar. La terminación .ASM es innecesaria. El ensamblador crea dos ficheros a partir de factor.asm que son factor.obj (código máquina traducido) y factor.lst (listado del programa). El fichero .obj se crea sólo si no ha habido errores de compilación. Para que se genere el fichero de listado es necesario escribir: c:\> TASM /zi factor,,factor donde la segunda aparición de la palabra factor es el nombre del fichero listado. La opción /zi sólo es necesaria si se quiere producir código adicional para poder hacer "debug" del programa. El fichero factor.obj necesita ser "linkado" (encadenado) para poder ejecutarse. Para hacer el link hay q ue escribir c:\> TLINK /v factor El fichero generado es factor.exe y es un fichero ejecutable a falta de la asignación de valores a los diferentes segmentos del programa. Si este programa se ejecuta desde el PC, el sistema operativo DOS se encarga de asignar valores a los diferentes segmentos. Para observar esto se utilizará el programa de debug T D, que permite controlar la ejecución de programas en código máquina en el P C. Para ello se escribe: c:\> TD FACTOR Ejemplo de uso del TD. Entrar en el menú de VIEW y activar la ventana de CPU. Dicha ventana está compuesta por otras subventanas instrucciones datos registros registro de estado o flags pila Para pasar de una ventana a otra presionar TAB. Cada zona tiene un menú local al que se accede con ALT-F10. Presionando esta combinación de teclas desde la zona de instrucciones y poniendo en MIXED Yes, se tendrá un listado del programa fuente y el programa ensamblado. En general, desde cada menú local se pueden cambiar las distintas zonas de la memoria que se visualiza en cada ventana o b ien cambiar los valores de los registros. Para ejecutar un programa, acceder al menú RUN en el que se tienen diferentes opciones: Trace: ejecuta las instrucciones paso a paso Run: ejecuta hasta el final del programa Step: ejecuta hasta la instrucción localizada a continuación Cursor: ejecuta hasta la instrucción marcada con el cursor Es cada instante, la instrucción siguiente a ejecutar está marcada con una flecha.