Cálculo del Factorial en la arquitectura OCUNS, haciendo uso de la rutina de multiplicación propuesta en el ejercicio 9 del correspondiente práctico. start: fact: seguir: mult: loop: salir: ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; dir code lda RA, 4 00 8A04 dec RE store RA, 0(RE) call RO, fact load RA, 0(RE) inc RE hlt dec RE store R0, 0(RE) load RA, 1(RE) dec RA jg RA, seguir load R0, 0(RE) inc RE lda RA, 1 store RA, 0(RE) jmp R0 dec RE store RA, 0(RE) call R0, fact load RA, 0(RE) inc RE load R1, 0(RE) store RA, 0(RE) call R0, mult jmp R1 load R2, 0(RE) inc RE load R3, 0(RE) inc RE sub R4, R4, R4 jz R2, salir jz R3, salir add R4, R4, R2 dec R3 jz RF, loop dec RE store R4, 0(RE) jmp R0 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E 20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E 40 42 44 46 48 4A 4C EE00 7AE0 B00E 6AE0 DE00 F000 EE00 70E0 6AE1 EA00 AA0A 60E0 DE00 8A01 7AE0 C000 EE00 7AE0 B00E 6AE0 DE00 61E0 7AE0 B034 C100 62E0 DE00 63E0 DE00 1444 9208 9306 0442 E300 9FF8 EE00 74E0 C000 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Cargo en RA el parámetro del factorial. Esta instrucción y la sig implementan un PUSH(RA). Llamo a factorial. Esta instrucción y la sig implementan un POP(RA). Termina la máquina OCUNS. Hago un PUSH de R0 que es la dirección de retorno. Tomo el parám sin desapilar Decremento el parámetro Si es mayor que cero, salto Hace POP(R0) con la dirección de retorno. Fact(0)=Fact(1)=1. Reemplazo el tope con RA. Hace un return. Hace PUSH del parámetro que sacó decrementado en uno. Llama recursivamente a Fact Hace POP del resultado parcial a RA. POP de la dir de ret a R1 PUSH del resultado parcial. Mult TOPE y TOPE+1. Return con R1. POP del tope (1° operando). POP del tope (2° operando). Asigno cero a R4 (acumul). Si un operando es 0, salgo. Si el otro es 0, salgo. Sumo R2 al acumulador. Decremento R3. Salto a loop. Hago PUSH(R4) que es el resultado de la mult. Termina el proc mult. Recordemos que la pila se organiza usando RE como Stack Pointer y la pila crece de las direcciones más altas de memoria hacia las más bajas. Un PUSH(R1) se implementa como: DEC RE STORE R1,0(RE) Mientras que un POP(R2) se implementa como: LOAD R2,0(RE) INC RE En la dirección 2C y 2E se dice que se hace POP(R1) y PUSH(RA). Sin embargo solo aparecen 2 instrucciones. Esto se debe a que el INC RE y DEC RE no tienen sentido al quedar juntos: load R1, 0(RE) inc RE dec RE store RA, 0(RE)