___________________________________________________________________________ | | | bhats curso 2006/2007 - Bajo Nivel - Notas 0x003 http://www.bhats.org | |___________________________________________________________________________| Justificado a 77 columnas MAX. ÍNDICE ====== ___________________________________________________________________________ | Título | NÚM | |-----------------------------------------------------------------|---------| | Introducción. | 0x000 | | POCs. | 0x001 | |_________________________________________________________________|_________| INTRODUCCIÓN - 0x000 ==================== En estas notas se pondrán algunas demostraciones de concepto (POCs), de menús por consola en ensamblador para MASM32 y NASM. MASM32: Windows NASM: Linux POCS - 0x001 =========== MASM32: ===== ; Directivas generales --------------------------------------- .386 ; Arquitectura 386 y compatibles. .model flat, stdcall ; Modelo plano, paso de parámetros STDCALL. option casemap:none ; No hace distinción entre mayúsculas y minúsculas. ; Directivas de inclusión ------------------------------------ include \masm32\include\windows.inc ; Es necesario usar cosas declaradas aquí como: NULL. include \masm32\include\kernel32.inc ; Se usa WriteConsole ... includelib \masm32\lib\kernel32.lib ; Declaración de procedimientos ------------------------------ MenuPrincipal PROTO MostrarMenuPrincipal PROTO ProcesarMenuPrincipalOpcion PROTO :BYTE MenuParticipantes PROTO MostrarMenuParticipantes PROTO ProcesarMenuParticipantesOpcion PROTO :BYTE MenuOrganizacion PROTO MostrarMenuOrganizacion PROTO ProcesarMenuOrganizacionOpcion PROTO :BYTE RecogeOpcion PROTO :DWORD LimpiarStdinHastaIntro PROTO MenuOpcionDesconocida PROTO ; Definición de Constantes simbólicas ------------------------- RCNL EQU 0Dh, 0Ah ; Retorno de Carro y Nueva Linea. INTRO EQU 0A0Dh ; WORD que se almacena en stdin cuando pulsamos intro en consola. NULLOPCION EQU 00h ; Opción NULA ningún menú podrá tener la opción 0. MENU_PRINCIPAL_OPCION_SALIDA EQU 33h ; Opcion de salida del menú principal. MENU_PARTICIPANTES_OPCION_SALIDA EQU 34h ; Opcion de salida del menú participantes. MENU_ORGANIZACION_OPCION_SALIDA EQU 34h ; Opcion de salida del menú organización. MENU_PARTICIPANTES_NUMERICO EQU 32h ; Opción por la que se accede al menú participantes mediante el menú principal. MENU_ORGANIZACION_NUMERICO EQU 31h ; Opción por la que se accede al menú organización mediante el menú principal. ; Secciones --------------------------------------------------- .data ; Sección de datos iniciados a un valor. ; Cadenas de caracteres de los menús. menu_principal db RCNL, ; Usar "RCNL" es similar a usar '\n' en C. " M E N U P R I N C I P A L:", RCNL, " ==========================", RCNL, " 1) Participantes bhats.", RCNL, " 2) Organizacion bhats.", RCNL, " 3) Salir.", RCNL, RCNL, \ " Introduzca opcion: " menu_participantes db RCNL, " P A R T I C I P A N T E S B H A T S:", RCNL, " ====================================", RCNL, " 1) Agregar participantes.", RCNL, " 2) Borrar participantes.", RCNL, " 3) Modificar participantes.", RCNL, " 4) Volver al menu anterior.", RCNL, RCNL, \ " Introduzca opcion: " menu_organizacion db RCNL, " O R G A N I Z A C I O N B H A T S:", RCNL, " ==================================", RCNL, " 1) Ver organizacion.", RCNL, " 2) Agregar organizador.", RCNL, " 3) Borrar organizador.", RCNL, " 4) Volver al menu anterior.", RCNL, RCNL, \ " Introduzca opcion: " menu_opcion_desconocida db " Opcion desconocida.", RCNL .data? ; Sección de datos no iniciados a un valor. STDInPutHandle HANDLE ? ; Manejador de STDIN. STDOutPutHandle HANDLE ? ; Manejador de STDOUT. Tmp DWORD ? ; Variable de ámbito general de tipo DWORD. Tmp2 WORD ? ; Variable de ámbito general de tipo WORD. .code ; Sección de código ejecutable. ; ----------------- Funciones del programa ------------ ; MenuPrincipal PROC LOCAL Opcion:BYTE ; Declaramos la variable local Opcion. bucle_menu_principal: CALL MostrarMenuPrincipal LEA EAX, Opcion PUSH EAX ; Ponemos en la pila la dirección de la variable Opción. CALL RecogeOpcion LEA EAX, Opcion PUSH [EAX] ; Ponemos en la pila el valor de la variable Opción. CALL ProcesarMenuPrincipalOpcion CMP Opcion, MENU_PRINCIPAL_OPCION_SALIDA ; Condición de salida del bucle. JNZ bucle_menu_principal ; Imitamos a un DO WHILE de C. RET MenuPrincipal ENDP MostrarMenuPrincipal PROC PUSH NULL PUSH offset Tmp PUSH sizeof menu_principal PUSH offset menu_principal PUSH STDOutPutHandle CALL WriteConsole RET MostrarMenuPrincipal ENDP ProcesarMenuPrincipalOpcion proc Opcion:BYTE ; Imitamos a un SWITCH CASE de C. Procesar_primera_opcion: CMP Opcion, MENU_ORGANIZACION_NUMERICO ; case JNZ Procesar_siguiente_opcion ; Si el case no se cumple vamos a la siguiente comprobación. CALL MenuParticipantes ; Instrucción si el case se cumple. JMP final ; break; Procesar_siguiente_opcion: CMP Opcion, MENU_PARTICIPANTES_NUMERICO JNZ Procesar_salida_opcion CALL MenuOrganizacion JMP final Procesar_salida_opcion: CMP Opcion, MENU_PRINCIPAL_OPCION_SALIDA JNZ default JMP final ; Si no se cumple ninguna de las anteriores, se cumple esta. default: CALL MenuOpcionDesconocida ; Omitimos "break;" de cortesía. final: RET ProcesarMenuPrincipalOpcion ENDP MenuParticipantes PROC LOCAL Opcion:BYTE bucle_menu_paricipantes: CALL MostrarMenuParticipantes LEA EAX, Opcion PUSH EAX CALL RecogeOpcion LEA EAX, Opcion PUSH [EAX] CALL ProcesarMenuParticipantesOpcion CMP Opcion, MENU_PARTICIPANTES_OPCION_SALIDA JNZ bucle_menu_paricipantes RET MenuParticipantes ENDP MostrarMenuParticipantes PROC PUSH NULL PUSH offset Tmp PUSH sizeof menu_participantes PUSH offset menu_participantes PUSH STDOutPutHandle CALL WriteConsole RET MostrarMenuParticipantes ENDP ProcesarMenuParticipantesOpcion PROC Opcion:BYTE Procesar_salida_opcion: CMP Opcion, MENU_PARTICIPANTES_OPCION_SALIDA JNZ default JMP final default: CALL MenuOpcionDesconocida final: RET ProcesarMenuParticipantesOpcion ENDP MenuOrganizacion PROC LOCAL Opcion:BYTE bucle_menu_organizacion: CALL MostrarMenuOrganizacion LEA EAX, Opcion PUSH EAX CALL RecogeOpcion LEA EAX, Opcion PUSH [EAX] CALL ProcesarMenuOrganizacionOpcion CMP Opcion, MENU_ORGANIZACION_OPCION_SALIDA JNZ bucle_menu_organizacion RET MenuOrganizacion ENDP MostrarMenuOrganizacion PROC PUSH NULL PUSH offset Tmp PUSH sizeof menu_organizacion PUSH offset menu_organizacion PUSH STDOutPutHandle CALL WriteConsole RET MostrarMenuOrganizacion ENDP ProcesarMenuOrganizacionOpcion PROC Opcion:BYTE Procesar_salida_opcion: CMP Opcion, MENU_ORGANIZACION_OPCION_SALIDA JNZ default JMP final default: CALL MenuOpcionDesconocida final: RET ProcesarMenuOrganizacionOpcion ENDP ; Recoge una BYTE de STDIN (asumiendo que esa es la opción) y luego lo limpia, hasta encontrar el "RCNL", ; en caso de que seguidamente del BYTE esté "RCNL" se asume que ha metido una opción incorrecta, ya que ; el rango de opciones válida son de 1 BYTE + "RCNL", sin ser el BYTE: NULLOPCION. RecogeOpcion PROC Opcion:DWORD PUSH NULL PUSH offset Tmp PUSH sizeof BYTE LEA EAX, Opcion PUSH [EAX] PUSH STDInPutHandle CALL ReadConsole CALL LimpiarStdinHastaIntro CMP EAX, 00h ; Si se ha limpiado en STDIN algún BYTE para llegar a encontrar JNZ salida ; RCNL (descontando el primer BYTE de la opción), no es válido LEA EAX, Opcion ; el primer BYTE leido como opción. MOV EAX, [EAX] MOV BYTE PTR [EAX], NULLOPCION ; Y asignamos el valor de opción NULA a la Opción. salida: RET RecogeOpcion ENDP ; Función que limpia Stdin hasta encontrar el "RCNL", devuelve 01h si se ha encontrado el "RCNL" ; Sin tener que limpiar ningún otro carácter antes, en caso contrario devuelve 00h, el valor lo devolverá ; siempre en EAX (DWORD). LimpiarStdinHastaIntro PROC LOCAL Flag:DWORD ; Variable flag, valor de RETORNO. MOV Flag, 01h ; Iniciamos a valor: "NO SE LIMPIADO OTRO CARACTER EXCEPTO EL RCNL". PUSH NULL PUSH offset Tmp PUSH sizeof WORD PUSH offset Tmp2 PUSH STDInPutHandle CALL ReadConsole CMP Tmp2, INTRO JZ salida MOV Flag, 00h; Se tendrá que limpiar caracteres para llegar hasta "RCNL". ; Método de los dos BYTES y rotación (explicado en el .txt). bucle_limpia_stdin: ROL WORD PTR Tmp2, 08h PUSH NULL PUSH offset Tmp PUSH sizeof BYTE PUSH offset [Tmp2 + 1] PUSH STDInPutHandle CALL ReadConsole CMP Tmp2, INTRO ; Condición de salida, (estilo DO WHILE C). JNZ bucle_limpia_stdin salida: MOV EAX, Flag ; Retornamos el valor de Flag. RET LimpiarStdinHastaIntro ENDP ; Función que muestra el mensaje de opción desconocida. MenuOpcionDesconocida PROC PUSH NULL PUSH offset Tmp PUSH sizeof menu_opcion_desconocida PUSH offset menu_opcion_desconocida PUSH STDOutPutHandle CALL WriteConsole RET MenuOpcionDesconocida ENDP ; ------------ ENTRY POINT ------------------------- ; start: PUSH STD_INPUT_HANDLE CALL GetStdHandle ; Obtenemos manejador STDIN. MOV STDInPutHandle, EAX PUSH STD_OUTPUT_HANDLE CALL GetStdHandle ; Obtenemos manejador STDOUT. MOV STDOutPutHandle, EAX CALL MenuPrincipal ; Llamamos al menú principal. RET ; Fin de la ejecución del programa. end start ; By David Reguera García, http://www.bhats.org 2006/2007, David Reguera García@bhats.org ; -------------------------------------------------------------- ; ; EOF ; ; -------------------------------------------------------------- ; NASM: ==== ; Es necesario ensamblarlo con el parámetro -t (por las directivas de TASM). ; Por ejemplo: ; nasm -t -f elf prueba.asm && gcc prueba.o -o prueba && ./prueba ; Buscar c32.mac por google. %include "c32.mac" RCNL EQU 0x0A STDIN EQU 0x01 STDOUT EQU 0x00 sys_write EQU 0x04 sys_read EQU 0x03 NULLOPCION EQU 0x00 sizeof_byte EQU 0x01 MENU_PRINCIPAL_OPCION_SALIDA EQU 0x33 ; Opcion de salida del menú principal. MENU_PARTICIPANTES_OPCION_SALIDA EQU 0x34 ; Opcion de salida del menú participantes. MENU_ORGANIZACION_OPCION_SALIDA EQU 0x34 ; Opcion de salida del menú organización. MENU_PARTICIPANTES_NUMERICO EQU 0x32 ; Opción por la que se accede al menú participantes mediante el menú principal. MENU_ORGANIZACION_NUMERICO EQU 0x31 ; Opción por la que se accede al menú organización mediante el menú principal. SECTION .data menu_principal db RCNL, db ' M E N U P R I N C I P A L:', RCNL, db ' ==========================', RCNL, db ' 1) Participantes bhats.', RCNL, db ' 2) Organizacion bhats.', RCNL, db ' 3) Salir.', RCNL, RCNL, db ' Introduzca opcion: ' menu_principal_size EQU $-menu_principal menu_participantes db RCNL, db ' P A R T I C I P A N T E S B H A T S:', RCNL, db ' ====================================', RCNL, db ' 1) Agregar participantes.', RCNL, db ' 2) Borrar participantes.', RCNL, db ' 3) Modificar participantes.', RCNL, db ' 4) Volver al menu anterior.', RCNL, RCNL, db ' Introduzca opcion: ' menu_participantes_size EQU $-menu_participantes menu_organizacion db RCNL, db ' O R G A N I Z A C I O N B H A T S:', RCNL, db ' ==================================', RCNL, db ' 1) Agregar organizador.', RCNL, db ' 2) Borrar organizador.', RCNL, db ' 3) Modificar organizador.', RCNL, db ' 4) Volver al menu anterior.', RCNL, RCNL, db ' Introduzca opcion: ' menu_organizacion_size EQU $-menu_organizacion menu_opcion_desconocida db ' Opcion desconocida.', RCNL menu_opcion_desconocida_size EQU $- menu_opcion_desconocida SECTION .text global main PROC MenuPrincipal %stacksize flat %assign %$localsize 0x00 %local Opcion:BYTE .bucle: CALL MostrarMenuPrincipal LEA EAX, [Opcion] PUSH EAX CALL RecogeOpcion LEA EAX, [Opcion] PUSH dword [EAX] CALL ProcesarMenuPrincipalOpcion CMP byte [Opcion], MENU_PRINCIPAL_OPCION_SALIDA JNZ .bucle ENDPROC PROC MostrarMenuPrincipal MOV EDX, menu_principal_size MOV ECX, menu_principal MOV EBX, STDOUT MOV EAX, sys_write INT 0x80 ENDPROC PROC ProcesarMenuPrincipalOpcion %stacksize flat %arg Opcion:byte .Procesar_primera_opcion: CMP byte [Opcion], MENU_ORGANIZACION_NUMERICO ; case JNZ .Procesar_siguiente_opcion ; Si el case no se cumple vamos a la siguiente comprobación. CALL MenuParticipantes ; Instrucción si el case se cumple. JMP .final ; break; .Procesar_siguiente_opcion: CMP byte [Opcion], MENU_PARTICIPANTES_NUMERICO JNZ .Procesar_salida_opcion CALL MenuOrganizacion JMP .final .Procesar_salida_opcion: CMP byte [Opcion], MENU_PRINCIPAL_OPCION_SALIDA JNZ .default JMP .final ; Si no se cumple ninguna de las anteriores, se cumple esta. .default: CALL MenuOpcionDesconocida ; Omitimos "break;" de cortesía. .final: ENDPROC PROC MenuParticipantes %stacksize flat %assign %$localsize 0x00 %local Opcion:BYTE .bucle: CALL MostrarMenuParticipantes LEA EAX, [Opcion] PUSH EAX CALL RecogeOpcion LEA EAX, [Opcion] PUSH DWORD [EAX] CALL ProcesarMenuParticipantesOpcion CMP byte [Opcion], MENU_PARTICIPANTES_OPCION_SALIDA JNZ .bucle ENDPROC PROC MostrarMenuParticipantes MOV EDX, menu_participantes_size MOV ECX, menu_participantes MOV EBX, STDOUT MOV EAX, sys_write INT 0x80 ENDPROC PROC ProcesarMenuParticipantesOpcion %arg Opcion:byte .Procesar_salida_opcion: CMP byte [Opcion], MENU_PARTICIPANTES_OPCION_SALIDA JNZ .default JMP .final .default: CALL MenuOpcionDesconocida .final: ENDPROC PROC MenuOrganizacion %stacksize flat %assign %$localsize 0x00 %local Opcion:BYTE .bucle: CALL MostrarMenuOrganizacion LEA EAX, [Opcion] PUSH EAX CALL RecogeOpcion LEA EAX, [Opcion] PUSH DWORD [EAX] CALL ProcesarMenuOrganizacionOpcion CMP byte [Opcion], MENU_ORGANIZACION_OPCION_SALIDA JNZ .bucle ENDPROC PROC MostrarMenuOrganizacion MOV EDX, menu_organizacion_size MOV ECX, menu_organizacion MOV EBX, STDOUT MOV EAX, sys_write INT 0x80 ENDPROC PROC ProcesarMenuOrganizacionOpcion %arg Opcion:byte .Procesar_salida_opcion: CMP byte [Opcion], MENU_ORGANIZACION_OPCION_SALIDA JNZ .default JMP .final .default: CALL MenuOpcionDesconocida .final: ENDPROC PROC RecogeOpcion %stacksize flat %arg Opcion:dword MOV EBX, STDIN MOV EAX, sys_read LEA ECX, [Opcion] MOV ECX, [ECX] MOV EDX, sizeof_byte INT 0x80 CALL LimpiarStdinHastaIntro ENDPROC PROC LimpiarStdinHastaIntro %stacksize flat %assign %$localsize 0x00 %local byte_recp:BYTE .bucle: MOV EBX, STDIN MOV EAX, sys_read LEA ECX, [byte_recp] MOV EDX, sizeof_byte INT 0x80 ENDPROC PROC MenuOpcionDesconocida MOV EDX, menu_opcion_desconocida_size MOV ECX, menu_opcion_desconocida MOV EBX, STDOUT MOV EAX, sys_write INT 0x80 ENDPROC main: CALL MenuPrincipal RET END NOTA: En el NASM no se verifica la correcta entrada, es decir: 33 INTRO, será equivalente a 3 INTRO, como ejercicio personal se plantea hacerlo. By David Reguera García, http://www.bhats.org 2006-2007, David Reguera García@bhats.org \===========================================================================/ EOF /===========================================================================\