; PROGRAMA: SWITCH
; Ejecuta un menu, recoge la opcion y despliega un mensaje segun la opcion
.386 ; compatible con 80386 y posteriores
.model flat, stdcall ; modo 32 bits protegido y convencion de llamadas
.stack 4096 ; Tamaño de la pila...
;=============================================================
;stdio.h
include c:\masm32\include\msvcrt.inc
includelib c:\masm32\lib\msvcrt.lib
;ExitProcess
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
;=============================================================
.data
opciones db "Escoge una opcion:",13,10,"1.",13,10,"2.",13,10,"0.Salir",13,10,">",0
formatoi db "%ld",0
cad1 db 13,10,"Opcion 1 escogida.",13,10,13,10,0
cad2 db 13,10,"Opcion 2 escogida.",13,10,13,10,0
cadsalir db 13,10,"Has escogido salir.",13,10,13,10,0
endl db 13,10,0
.data?
; Las dos componentes son el valor del caso y la direccion
; y de la funcion/codigo que ejecuta el codigo asociado
SwitchTonto dd 4 dup(?) ; dos elementos tipo switch case: [caso,funcion]
opcion dd ?
.code
main PROC
mov ebx , OFFSET SwitchTonto ; cargamos la direccion de los pares valor-funcion
xor eax , eax ; dejamos eax a cero
mov eax , 1 ; pasamos a eax el primer caso del switch
mov [ebx] , eax ; lo guardamos en el primer par
mov [ebx + 4] , op1 ; y copiamos la direccion de la funcion que maneja el caso
mov eax , 2 ; lo mismo con el segundo caso del switch
mov [ebx + 8] , eax
mov [ebx + 12] , op2
;do{
MENU_INI:
sub esp , 4 ;hacemos hueco en la pila para el valor de retorno
call menu ; desplegamos la informacion y en la pila vuelve la opcion
pop eax ; recogemos la opcion elegida
mov esi , 2 ; esi sera el subindice para recorrer el array del switch
SWITCH_INI: ; principio de la eleccion
dec esi ; pasamos al siguiente indice
cmp esi , 0FFFFFFFFh ; si es -1
jz SWITCH_FIN ; hemos terminado de leer el array y salimos del switch
cmp eax , [ebx + 8 * esi] ; comparamos el valor devuelto por menu con el del caso
jnz SWITCH_INI ; si no son iguales, vamos a comprobar el siguiente caso
;en este punto eax ya no nos sirve, ya que hemos encontrado la opcion elegida
mov eax , 8 ; calculamos el desplazamiento dentro del par valor-funcion
mul esi ; en el que se encuentra el offset de la direccion de la funcion:
add eax , 4 ; 8 * indice + 4
call DWORD PTR [ebx + eax] ; y llamamos a la funcion que maneja el caso
SWITCH_FIN:
test eax , eax ; si la opcion elegida no es cero (salir)
jnz MENU_INI ; volvemos a llamar al menu
MENU_FIN:
;}while(opcion != 0);
call salir ; desplegamos el mensaje de salida
call crt_getchar ; esperamos a pulsar intro
push 0 ; y terminamos el programa
call ExitProcess
ret
main ENDP
; long menu(void)
menu PROC
pushad ; guardamos los registros para devolverlos como estaban
; do{}while(opcion<0 || opcion>2)
PEDIR_OPCION_INI:
push OFFSET endl ; imprimimos una nueva linea para separar el menu de lo anterior
call crt_printf
add esp , 4 ; "sacamos" el paramtro de printf de la pila
push OFFSET opciones ; mostramos las opciones
call crt_printf
add esp , 4 ; y dejamos la pila apuntando a los registros pusheados
push OFFSET opcion ; ponemos la direccion de la variable opcion
push OFFSET formatoi ; la cadena de formato para scanf
call crt_scanf ; llamamos a scanf
add esp , 8 ; y desplazamos la pila tantas posiciones como bytes tenian los parametros
call limpiarbuf ; sacamos todos los datos que quedan en la entrada
mov eax , opcion ; pasamos a eax el valor introducido
cmp eax , 0 ; si el valor es menor que cero
jl PEDIR_OPCION_INI
cmp eax , 2 ; o mayor que 2
jg PEDIR_OPCION_INI ; volvemos a pedir el dato
PEDIR_OPCION_FIN:
mov edi , esp ; copiamos en edi el puntero de pila
mov [edi + 36] , eax ; y guardamos la opcion elegida despues de los 8 registros y la direccion de retorno
popad ; dejamos los registros como estaban al entrar en la funcion
ret ; y regresamos
menu ENDP
limpiarbuf PROC
pushad ; guardamos los registros generales
;while(getchar() != '\n')
LIMPIEZA_INI:
call crt_getchar
cmp eax , 10
jnz LIMPIEZA_INI
LIMPIEZA_FIN:
popad ; y dejamos los registros como antes de la llamada
ret ; volvemos
limpiarbuf ENDP
; imprime el mensaje de que se ha elegido la opcion 1
op1 PROC
pushad
push OFFSET cad1
call crt_printf
add esp , 4
popad
ret
op1 ENDP
; imprime el mensaje de que se ha elegido la opcion 2
op2 PROC
pushad
push OFFSET cad2
call crt_printf
add esp , 4
popad
ret
op2 ENDP
; imprime el mensaje de que se ha elegido salir
salir PROC
pushad
push OFFSET cadsalir
call crt_printf
add esp , 4
popad
ret
salir ENDP
END main