¿Podriais darme algun consejo sobre estilo antes de avanzar mas?

Iniciado por do-while, 12 Agosto 2010, 21:47 PM

0 Miembros y 1 Visitante están viendo este tema.

do-while

¡Buenas!

Hace pocos dias empece a leer Assembly_Language_For_Intel_based_computers (solo voy por el capitulo 7). Ya tenia una pequeña base sobre las instrucciones en ensamblador gracias a que he empezado tambien a seguir el curso de ingenieria inversa de Ricardo Narvaja, asi que he ido haciendo algun ejercicio basandome en lo que habia estudiado del libro y en lo que habia visto a traves del debuger. No he tenido ningun problema ni para escribir el codigo ni para depurar los programas, pero antes de seguir avanzando, me gustaria que si podeis, los que mas tiempo llevais utilizando ensamblador, me dieseis algun consejo sobre estilo o alguna otra cosa que se pueda mejorar para obtener claridad. Se por C que es muy importante mantener el codigo ordenado y claro, pero no se si lo que estoy aplicando hasta ahora sirve solo a pequeña escala y luego al meterme en camisas de once varas acabare liado...

Bueno, aqui dejo el codigo y ¡que empieze el chaparron!

Un ultimo aviso, no he llegado a las interrupciones ni conozco la parte del API de Windows que controla la consola, asi que la entrada/salida la hago con funciones de C.

Ah, y el ensamblador que utilizo es MASM32, no se si hay diferencias con respecto al resto... solo llevo 5 dias con esto...

Código (asm) [Seleccionar]

; 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


¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!