Apuntes primer parcial 03/10/2006 (Organización del Computador II)

De Cuba-Wiki
Revisión del 00:30 4 oct 2006 de 157.92.4.151 (discusión)
(difs.) ← Revisión anterior | Revisión actual (difs.) | Revisión siguiente → (difs.)

Strings

Averigue el puntero/longitud a la meseta mas larga Meseta es repeticion de letras iguales

Se anidan dos ciclos/funciones/macros.

Macro interna longMeseta:

Dado esi (en strings, puntero al src, en gral), devuelve la longitud de la meseta q empieza en esi. Requiere: esi al comienzo de la meseta bit de direcciones en avanzar Asegura: esi en el caracter siguiente a la meseta ecx tiene la longitud del resto de la cadena ebx es la longitud de la meseta

Se puede hacer mediante la instruccion scas. Se usa un lodsb para levantar el 1er byte de la meseta, el scas para iterar, y un repe para iterar mientras sea igual. La longitud de la meseta es la diferencia entre el esi del final y el esi del ppio.

Se debe llamar a longMeseta para recorrer toda la cadena, en un ciclo externo.

while ecx>0 longMeseta ebx= max(ebx, max_actual)

Instruccion LEA

lea reg, [reg1 + reg2*t + k]

Tiene el mismo formato que un modo de direccionamiento Donde t es 1,2,4,8; k es un inmediato de 32 bits; y los registros son de 32 bits

Pila

El push decrementa El pop incrementa

Numeros grandes

Para laburar con enteros grandes, se pueden hacer suposiciones sobre el tamaño maximo de los mismos. No hay que validar de mas en assembler, la idea es funciones rapidas.


Multiplicacion de numeros grandes por potencias chicas de 2

Sea el numero 08 00 CA FE Lo consideramos "grande" para este ejercicio

Lo queremos multiplicar por 2 En el primer byte uso un SHL/SAL 1 En los siguientes, RCL, rotate left circular

El shift saca el bit mas significativo y lo mete en el CF El RCL hace un shift, mete el CF en el menos significativo, y pisa el CF con el mas significativo q saco afuera El ROL pasa directamente del mas significativo al menos, y copia el mas significativo al CF

El SHR mete un cero en el mas significativo, y el SAL repite el 7mo bit. Tiran el bit menos significativo que sacaron en el CF. Para dividir hay que ir del dword mas significativo al menos.

Para multiplicar por 4, no conviene correr 2 veces el algoritmo anterior por los accesos a memoria Como se necesitarian 2 carry flag, se puede ir tirando los bits del carry a otro registro, haciendo RCL del reg que tiene el numero para cargar el carry, despues otro RCL contra el reg adicional para guardar ahi el carry, y asi sucesivamente. Antes de seguir a la proxima dword, se shiftea lo necesario para pasar los bits guardados de la parte mas alta a la mas baja. Otra posibilidad es guardar los bits mas significativos con operaciones logicas: copiar el registro y hacer un and con una mascara que deje solo los mas altos que se quieran guardar.


Multiplicar numeros grandes con signo

Para multiplicar numeros grandes, primero pasar los dos a positivo y despues multiplicar, y ver cual deberia ser el signo del resultado.

Para cambiar de signo, empiezo por el menos significativo y voy negando y sumando uno (el carry despues de la 1er dword). La negacion se puede hacerla en los registros, no negarlo en memoria. Hay que guardar el carry en ese caso para saber que sumar.


Multiplicar un numero grande por un registro de 32bit

Se tiene un numero grande en memoria, en esi el puntero. En ebx el numero por el que se quiere multiplicar. Cargo la parte baja en eax, multiplico por ebx y queda el resultado en edx:eax. En la 1er iteracion, se puede bajar eax directamente. La parte alta, edx, es necesario guardarla (x ej en ecx).

mov eax, [esi] mul ebx mov [edi], eax mov ecx, edx

Luego hay que sumar eax y ecx antes de bajar a memoria. El carry que se produce por sumar ecx y edx hay que pasarlo a edx. Ese pasaje de carry NO puede producir carry, por el tamaño de los numeros.

(incPunteros) mov eax, [esi] mul ebx add eax, ecx adc edx, 0 mov [edi], eax mov ecx, edx