Translate

sábado, 5 de mayo de 2012

Crear una máquina virtual en Matlab ( léase compilador )

Un poco de teoría

Primero conoceremos que son los ensambladores :3

Ensambladores

  1. Ensambladores de una pasada
    1. Con salida en Binario ( Conocidos también como load and go )
    2. Con salida simbólica-binaria
  2. Ensambladores de dos pasadas

Ensamblador de dos pasadas

En este pequeño tutorial se realizará un ensamblador de dos pasadas.

Primer paso

En el primer paso la prioridad es obtener las tablas

Pasos a realizar durante el primer paso

  • Tratamiento de etiquetas( instrucciones ).
  • Buscar en tabla de símbolos (si no está, pasar al siguiente paso).
  • Insertar en tabla de símbolos.
  • Tratamiento de código de operación.
  • Buscar en tabla de código de operación y actualizar campo de dirección.
  • Escribir código de operación.
  • Buscar en tabla de pseudo- instrucciones y hacer el tratamiento de la pseudo-instrucción.
  • Análisis del operando (en caso de la creación de un código intermedio).
  • Almacenar en tabla de símbolos.
  • Buscar en tabla de símbolos.
  • Sustituir por dirección en tabla de símbolos.

Segundo paso

Sus objetivos son obtener el programa en simbólico y binario, crear las tablas para el linker ( enlazador o ligador ), y localizar las variables ( puede incluir un dump ).

Pasos a realizar durante el segundo paso

  • Tratamiento del código de operación
  • Buscar en tabla de código de operación.
    • Actualizar contador de direcciones.
    • Buscar tabla de pseudo-instrucción (si es símbolo).
  • Tratamiento del operando.
    • Buscar en tabla de símbolo (si es símbolo).
    • Obtener valor
  • Escribir código objeto

Tablas a usar


( pendiente aunque ya estén en el código :P )


Codificando

Borrar variables anteriores y limpiar área de impresión





%% Universidad Autónoma de Tlaxcala
% Blanca Leticia Milácatl López
%%



%% Inicialización
clear, clc
%% TABLAS
%Para poder realizar la conversión se proveen las siguientes tablas
%% tabla de direccion simbolica de los simbolos de direccion
tabla_direccion_simbolica_simbolos_direccion = [];

codigo_de_caracteres_hexadecimales_letras = ['A'; 'M'; 'Y';
    ' '; 'B'; 'N'; 'Z'; '('; 'C'; 'O';
    '0'; ')'; 'D'; 'P'; '1'; '*'; 'E';
    'Q'; '2'; '+'; 'F'; 'R'; '3'; ';';
    'G'; 'S'; '4'; '-'; 'H'; 'T'; '5';
    '.'; 'I'; 'U'; '6'; '/'; 'J'; 'V';
    '7'; '='; 'K'; 'W'; '8'; 'L';
    'X'; '9']; %caracter y código

diagn = ['\n'];

codigo_de_caracteres_hexadecimales_hexa = ['41'; '4D'; '59';
    '20'; '42'; '4E'; '5A'; '28'; '43'; '4F';
    '30'; '29'; '44'; '50'; '31'; '2A'; '45';
    '51'; '32'; '2B'; '46'; '52'; '33'; '2C';
    '47'; '53'; '34'; '2D'; '48'; '54'; '35';
    '2E'; '49'; '55'; '36'; '2F'; '4A'; '56';
    '37'; '3D'; '4B'; '57'; '38'; '4C';
    '58'; '39']; %caracter y código

diagn_num = ['OD'];

%% tabla del conjunto de instrucciones a hexa
conjunto_instrucciones=['AND',% 0 or 8 AND M to AC
'ADD',% 1 or 9 Add M to AC, carry to E
'LDA',% 2 or A Load AC from M
'STA',% 3 or B Store AC in M
'BUN',% 4 or C Branch unconditionally to m
'BSA',% 5 or D Save return address in m and branch to m+1
'ISZ',% 6 or E Increment M and skip if zero
'CLA',% 7800 Clear AC
'CLE',% 7400 Clear E
'CMA',% 7200 Complement AC
'CME',% 7100 Complement E
'CIR',% 7080 Circulate right E and AC
'CIL',% 7040 Circulate left E and AC
'INC',% 7020 Increment AC, carry to E
'SPA',% 7010 Skip if AC is positive
'SNA',% 7008 Skip if AC is negative
'SZA',% 7004 Skip if AC is zero
'SZE',% 7002 Skip if E is zero
'HLT',% 7001 Halt computer
'INP',% F800 Input information and clear flag
'OUT',% F400 Output information and clear flag
'SKI',% F200 Skip if input flag is on
'SKO',% F100 Skip if output flag is on
'ION',% F080 Turn interrupt on
'IOF'];%F040 Turn interrupt off

hexa_instrucciones ={'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7800',
'7400',
'7200',
'7100',
'7080',
'7040',
'7020',
'7010',
'7008',
'7004',
'7002',
'7001',
'F800',
'F400',
'F200',
'F100',
'F080',
'F040'
};

%% Leer el código fuente
fid = fopen('miarchivo.txt','r');
cadenas = fread(fid, '*char')';
fclose(fid);

%% Separar parte de fuconamiento y área de datos

%cadenas= textscan(fid,'%s')
%cadenas=cell2struct(textread('miarchivo.txt','%s', 'whitespace', ''),,1)
[f,c] = size(cadenas);
indice = findstr(cadenas,'HLT')
primeraparte = cadenas(1:indice+3)
segundaparte = cadenas(indice+5:c)

%% Obtener la posicion inicial en memoria
[ppf,ppc] = size(segundaparte);
pos_inicial = findstr(primeraparte,'ORG')+3;
cadnasdepuesorg=cadenas(pos_inicial-3:c)
inicio_memoria = primeraparte(pos_inicial:ppc);
inicio_memoria=textscan(inicio_memoria,'%d');
inicio_memoria=inicio_memoria{1};


%% obtiene la dirección de cada línea a partir de la posición inicial en
%% memoria

programasinorgend = cadnasdepuesorg(1:findstr(cadnasdepuesorg,'END')-1) %guardamos eliminando org y ends
lineas = strread(programasinorgend,'%s','delimiter',sprintf('\n'));
lineas = string(char(lineas))
[num_lineas,c]=size(lineas);

direcciones = [inicio_memoria:inicio_memoria+num_lineas]; %se necesitará pasar a hexadecimal despues

%% imprimir el programa ya con direcciones de referencia
for i=1:num_lineas-1
    %disp(direcciones(i))
    disp(sprintf('%s\t%s',num2str(direcciones(i)),lineas(i+1,:)));
end

% obtiene las líneas
programa_por_lineas = strread(cadenas,'%s','delimiter',sprintf('\n'));
for i=1:num_lineas-1
    %programa_por_lineas(i,:)=sprintf('%s\t%s',num2str(direcciones(i)),lineas(i+1,:));
    programa_por_lineas(i,:)={sprintf('%s\t%s',num2str(direcciones(i)),lineas(i+1,:))};
end
% compostura para que salga bien
n_programa_por_lineas=[cellstr(programa_por_lineas(1:num_lineas-1));cellstr(programa_por_lineas(num_lineas+1))];

disp('Programa con direcciones de memoria')
disp(n_programa_por_lineas)

%% Preparar la TABLA DE SIMBOLOS DE DIRECCION
[spf,spc] = size(segundaparte);
parte_tabla_simbolos = segundaparte(1:findstr(segundaparte,'END')-1)
parte_tabla_simbolos = strread(parte_tabla_simbolos,'%s','delimiter',sprintf('\n'));

[tsf,tsc]=size(parte_tabla_simbolos); %tamaño de la parte donde se saca la tabla de símbolos

tabla_simbolos=[];
valor_tabla_simbolos=[];
%ooops pequeño error, usar el k tiene las direcciones si se puede y guardar
%dirección y símbolo
for num_lineas_felices=1:1:tsf
    %valor_tabla_simbolos(num_lineas_felices)=
    [simbolo,resto] = strtok(parte_tabla_simbolos(num_lineas_felices,:));
    tabla_simbolos=[tabla_simbolos, simbolo];
    disp( simbolo );
    [tipo_dato,resto1]=strtok(resto(1,:));
    
    %pendiente:
    %tratar aquí x para saber el tipo de dato, si es DEC usar str2num
    %luego num2hexpara guardar su valor hexadecimal
    %si es HEX ya está en hexadecimal
    switch upper(char(tipo_dato))
        case 'DEC'
            num = str2num(char(resto1));
            hexad = num2hex(single(num));
            resto1 = hexad;
        case 'HEX'
            num = hex2dec(char(resto1));
            hexad = num2hex(single(num));
            resto1 = hexad;
        otherwise
            error('tipo de datos no reconocido')
    end
    
    valor_tabla_simbolos=[valor_tabla_simbolos;resto1];
    disp(resto1);
    
end
%%valor_tabla_simbolos=char(parte_tabla_simbolos) %no sé para que había
%%puesto esto XD

%simbolos_y_sus_valores(i,:)=strrep(parte_tabla_simbolos(i,:), tabla_simbolos(i,:), valor_tabla_simbolos(i,:)); % pendiente remplazar los
%valores en el programa con las direcciones


%obtener de direcciones los ´ltimos índces hasta el tamaño de simbolos
[datosf, datosc]=size(char(valor_tabla_simbolos));
[programaf,programac]=size(n_programa_por_lineas);

dir_inicio_remplazo = programaf-datosf;

programa_con_direcciones_muy_felices = n_programa_por_lineas; % pendiente cambiar tamañoi

instrucciones=[];
direcciones_instr = [];

for ind = programaf:-1:dir_inicio_remplazo+1
   cad=char(tabla_simbolos(1,programaf+1-ind));
   instr=cad(1:3)
   instrucciones=[instrucciones;instr];
    %programaf-ind
    direcciones_instr=[direcciones_instr;num2str( direcciones(dir_inicio_remplazo-1+(programaf-ind)) )];
    
   % valor_tabla_simbolos(programaf+1-ind,:)
    programa_con_direcciones_muy_felices(dir_inicio_remplazo+(programaf-ind)) = cellstr(sprintf('%s\t%s %s',num2str( direcciones(dir_inicio_remplazo-1+(programaf-ind)) ),instr,valor_tabla_simbolos(programaf+1-ind,:)))
end




copia_tabla_simbolos = tabla_simbolos;

%for i=1:dir_inicio_remplazo
%    strrep(copia_tabla_simbolos(i)
%end

%% encontrar los mnemónicos en las tablas y reemplazar

. . .


Notas

La variable fid es por file identifier o identificador de archivo, no confundir con find.
Este código es a fuerza bruta, no está optimizado.

He estado ayudando en este proyecto, más avances pronto. No olviden comentar.