(* programme comment‚ et expliqu‚ dans le livre *) (* LE DESASSEMBLEUR 8086 COLIBRI, publi‚ par *) (* L'INSTITUT PASCAL: *) (* 26 Rue Lamartine, 75009 PARIS *) (* Tel: (1) 42.85.10.82 *) begin l_bit_mot:= l_code_operation and 1; l_bit_direction:= (l_code_operation and 2) shr 1; l_bits_registre:= l_code_operation and 7; l_bit_registre_mot:= (l_code_operation and 8) shr 3; case l_code_operation of $37: met('aaa '); $D5: begin met('aad'); lis_octet_suivant(l_operande); if l_operande<> $0A then met(' ???_1'); end; $D4: begin met('aam'); lis_octet_suivant(l_operande); if l_operande<> $0A then met(' ???_2'); end; $3F: met('aas'); $10..$15: begin met('adc '); case l_code_operation of $10..$13 : traite_direction_mot; $14 : begin met('al, '); met_operande_un_octet; end; $15 : begin met('ax, '); met_operande_un_mot; end; end; end; $00..$05: begin met('add '); case l_code_operation of $00..$03 : traite_direction_mot; $04..$05 : traite_accumulateur_immediat; end; end; $20..$25: begin met('and '); case l_code_operation of $20..$23 : traite_direction_mot; $24..$25 : traite_accumulateur_immediat; end; end; $9A, $E8: begin met('call '); case l_code_operation of $9A : begin lis_entier_suivant(l_adresse); l_chaine:= f_entier_hexadecimal(l_adresse); lis_entier_suivant(l_adresse); l_chaine2:= f_entier_hexadecimal(l_adresse); met3(l_chaine2, ':', l_chaine); end; $E8 : begin lis_entier_suivant(l_adresse); met(f_ajoute_label_call(adresse+ l_adresse)); end; end; end; $98: met('cbw'); $F8: met('clc'); $FC: met('cld'); $FA: met('cli'); $F5: met('cmc'); $38..$3D: begin met('cmp '); case l_code_operation of $38..$3B: traite_direction_mot; $3C: begin traite_accumulateur_immediat; if l_operande in [$0..$7E] then affiche_caractere; end; $3D: traite_accumulateur_immediat; end; end; $A6: met('cmps b'); $A7: met('cmps w'); $99: met('cwd'); $27: met('daa'); $2F: met('das'); $48..$4F: begin met('dec '); traite_fin_registre; end; $D8..$DF: begin met('esc '); lis_octet_mode; traite_registre(l_chaine); met(l_chaine); end; $F6..$F7: begin lis_octet_mode; if l_bit_mot= 0 then begin case l_registre of 0 : begin met('test '); traite_bit_mot; met(', '); met_operande_un_octet; end; 1 : begin met('???_3'); end; 2 : begin met('not '); traite_bit_mot; end; 3 : begin met('neg '); traite_bit_mot; end; 4 : begin met('mul al, '); traite_mode; end; 5 : begin met('imul al, '); traite_mode; end; 6 : begin met('div al, '); traite_mode; end; 7 : begin met('idiv al, '); traite_mode; end; end; end else begin case l_registre of 0 : begin met('test '); traite_bit_mot; met(', '); met_operande_un_mot; end; 1 : begin met('???_4'); end; 2 : begin met('not '); traite_bit_mot; end; 3 : begin met('neg '); traite_bit_mot; end; 4 : begin met('mul ax, '); traite_mode; end; 5 : begin met('imul ax, '); traite_mode; end; 6 : begin met('div ax, '); traite_mode; end; 7 : begin met('idiv ax, '); traite_mode; end; end; end; end; $FE..$FF: begin lis_octet_mode; if l_bit_mot= 0 then begin case l_registre of 0 : begin met('inc b '); traite_mode; end; 1 : begin met('dec b '); traite_registre(l_chaine); met(l_chaine); end; else begin met('???_5'); end; end; end else begin case l_registre of 0 : begin met('inc w '); traite_mode; end; 1 : begin met('dec w '); traite_registre(l_chaine); met(l_chaine); end; 2 : begin traite_registre(l_chaine); met2('call ', l_chaine); end; 3 : begin traite_registre(l_chaine); met2('call ', l_chaine); end; 4 : begin met('jmp_ra '); traite_bit_mot; end ; 5 : begin met('jmp_er '); traite_bit_mot; end; 6 : begin met('push '); traite_bit_mot; end; 7 : met('???_7'); end; end; end; $F4: met('hlt'); $80..$82: begin lis_octet_mode; case l_registre of 0 : met('add '); 1 : met('or '); 2 : met('adc '); 3 : met('sbb '); 4 : met('and '); 5 : met('sub '); 6 : met('xor '); 7 : met('cmp '); end; traite_mode; met(', '); met_operande(l_bit_mot); end; $83: begin lis_octet_mode; case l_registre of 0 : met('add '); 1 : met('or '); 2 : met('adc '); 3 : met('sbb '); 4 : met('and '); 5 : met('sub '); 6 : met('xor '); 7 : met('cmp '); end; traite_mode; met(', '); met_operande(0); end; $E4..$E5, $EC..$ED: begin met('in '); case l_code_operation of $EC : met('al, dx'); $ED : met('ax, dx'); $E4..$E5 : traite_accumulateur_immediat; end; end; $40..$47: begin met('inc '); traite_fin_registre; end; $CC: met('int 3'); $CD: begin met('int '); met_operande_un_octet; commente_interruption; end; $CE: met('into'); $CF: met('iret'); $72: begin met('jb '); met_operande_relatif_un_octet; end; $76: begin met('jbe '); met_operande_relatif_un_octet; end; $E3: begin met('jcxz '); met_operande_relatif_un_octet; end; $74: begin met('je '); met_operande_relatif_un_octet; end; $7C: begin met('jl '); met_operande_relatif_un_octet; end; $7E: begin met('jle '); met_operande_relatif_un_octet; end; $E9..$EB: begin if l_code_operation= $EB then met('jmp_s ') else met('jmp '); case l_code_operation of $E9 : met_operande_relatif_un_mot; $EA : begin met_operande_un_mot; met(':'); met_operande_un_mot; end; $EB : begin met_operande_relatif_un_octet; end; end; end; $73: begin met('jnc '); met_operande_relatif_un_octet; end; $77: begin met('jnbe '); met_operande_relatif_un_octet; end; $75: begin met('jnz '); met_operande_relatif_un_octet; end; $7D: begin met('jnl '); met_operande_relatif_un_octet; end; $7F: begin met('jnle '); met_operande_relatif_un_octet; end; $71: begin met('jno '); met_operande_relatif_un_octet; end; $7B: begin met('jnp '); met_operande_relatif_un_octet; end; $79: begin met('jns '); met_operande_relatif_un_octet; end; $70: begin met('jo '); met_operande_relatif_un_octet; end; $7A: begin met('jp '); met_operande_relatif_un_octet; end; $78: begin met('js '); met_operande_relatif_un_octet; end; $9F: met('lahf '); $C5: begin met('lds '); lis_octet_mode; decode_registre(1, l_registre, l_chaine); met2(l_chaine, ', '); traite_registre(l_chaine); met(l_chaine); end; $8D: begin met('lea '); lis_octet_mode; decode_registre(1, l_registre, l_chaine); met2(l_chaine, ', '); traite_registre(l_chaine); met(l_chaine); end; $C4: begin met('les '); lis_octet_mode; decode_registre(1, l_registre, l_chaine); met2(l_chaine, ', '); traite_registre(l_chaine); met(l_chaine); end; $F0: met('lock'); $AC: met('lods b'); $AD: met('lods w'); $E2: begin met('loop '); met_operande_relatif_un_octet; end; $E0: begin met('loopnz '); met_operande_relatif_un_octet; end; $E1: begin met('loopz '); met_operande_relatif_un_octet; end; $88..$8C, $8E, $A0..$A3, $B0..$BF, $C6..$C7: begin met('mov '); case l_code_operation of $88..$8B : begin traite_registre_registre_memoire; end; $8C : begin lis_octet_mode; if l_registre> 3 then met('???_9') else begin l_bit_mot:= 1; traite_registre(l_chaine); met2(l_chaine, ', '); case l_registre of 0 : met('es'); 1 : met('cs'); 2 : met('ss'); 3 : met('ds'); end; end; end; $8E : begin lis_octet_mode; if l_registre> 3 then met('???_9') else begin l_bit_mot:= 1; traite_registre(l_chaine); case l_registre of 0 : met('es, '); 1 : met('cs, '); 2 : met('ss, '); 3 : met('ds, '); end; met(l_chaine); end; end; $A0 : begin met('al, ['); met_operande_un_mot; met(']'); end; $A1 : begin met('ax, ['); met_operande_un_mot; met(']'); end; $A2 : begin met('['); met_operande_un_mot; met('], al'); end; $A3 : begin met('['); met_operande_un_mot; met('], ax'); end; $B0..$BF : begin decode_registre(l_bit_registre_mot, l_bits_registre, l_chaine); met2(l_chaine, ', '); met_operande(l_bit_registre_mot); recupere_valeur_stockee_dans_registre; end; $C6..$C7 : begin lis_octet_mode; traite_registre(l_chaine); met2(l_chaine, ', '); met_operande(l_bit_mot); end; end; end; $A4: met('movs b'); $A5: met('movs w'); $90: met('nop'); $08..$0B, $0C..$0D: begin met('or '); case l_code_operation of $08..$0B : traite_direction_mot; $0C..$0D : traite_accumulateur_immediat; end; end; $E6..$E7, $EE..$EF: begin met('out '); case l_code_operation of $EE : met('dx, al'); $EF : met('dx, ax'); $E6..$E7 : traite_accumulateur_immediat; end; end; $07, $17, $1F, $58..$5F, $8F: begin met('pop '); case l_code_operation of $58..$5F : traite_fin_registre; $8F: begin lis_octet_mode; if l_registre<> 0 then met('???_10') else begin traite_registre(l_chaine); met(l_chaine); end; end; $07: met('es'); $17: met('ss'); $1F: met('ds'); end; end; $9D: met('popf'); $06, $0E, $1E, $16, $50..$57: begin met('push '); case l_code_operation of $06 : met('es'); $0E : met('cs'); $16 : met('ss'); $1E : met('ds'); $50..$57: traite_fin_registre; end; end; $9C: met('push_f'); $F2: met('rep'); $F3: met('rep_z'); $C2..$C3, $CA..$CB: begin met('ret '); case l_code_operation of $C2 : begin lis_entier_suivant(l_adresse); met2(f_entier_hexadecimal(l_adresse) , ' ; intra'); end; $C3 : ; $CA : begin lis_entier_suivant(l_adresse); met2(f_entier_hexadecimal(l_adresse) , ' ; inter'); end; $CB : met(' ; inter seg'); end; end; $9E: met('sahf'); $18..$1D: begin met('sbb '); case l_code_operation of $18..$1B : traite_direction_mot; $1C..$1B : traite_accumulateur_immediat; end; end; $AE: met('scas b'); $AF: met('scas w'); $26, $2E, $36, $3E: begin met('seg '); case l_code_operation of $26 : met('es'); $2E : met('cs'); $36 : met('ss'); $3E : met('ds'); end; end; $D0..$D3: begin lis_octet_mode; case l_registre of 0 : met('rol '); 1 : met('ror '); 2 : met('rcl '); 3 : met('rcr '); 4 : met('shl '); 5 : met('shr '); 6 : met('???_11'); 7 : met('sar '); end; if l_registre <> 6 then begin traite_registre(l_chaine); met(l_chaine); if l_bit_direction= 1 then met(', cl') else met(', 1'); end; end; $F9: met('stc'); $FB: met('sti'); $FD: met('std'); $AA: met('stos b'); $AB: met('stos w'); $28..$2D: begin met('sub '); case l_code_operation of $28..$2B : traite_direction_mot; $2C..$2D : traite_accumulateur_immediat; end; end; $84..$85, $A8..$A9: begin met('test '); case l_code_operation of $84..$85 : begin l_bit_direction:= 1; traite_registre_registre_memoire; end; $A8..$A9 : traite_accumulateur_immediat; end; end; $9B: met('wait'); $86..$87, $91..$97: begin met('xchg '); case l_code_operation of $86..$87 : begin lis_octet_mode; traite_registre(l_chaine); decode_registre(l_bit_mot, l_registre, l_chaine2); met3(l_chaine2, ', ', l_chaine) end; $91..$97 : traite_fin_registre; end; end; $D7: met('xlat'); $30..$35: begin met('xor '); case l_code_operation of $30..$33: begin traite_direction_mot; if (l_code_operation= $32) and (l_chaine= l_chaine2) then if l_chaine= 'ah' then l_ah_precedent:= 0 else if l_chaine= 'al' then l_al_precedent:= 0 else if l_chaine= 'bl' then l_bl_precedent:= 0 else if l_chaine= 'bh' then l_bh_precedent:= 0 else if l_chaine= 'cl' then l_cl_precedent:= 0 else if l_chaine= 'ch' then l_ch_precedent:= 0 else if l_chaine= 'dl' then l_dl_precedent:= 0 else if l_chaine= 'dh' then l_dh_precedent:= 0; end; $34..$35: traite_accumulateur_immediat; end; end; $0F, $60..$6F, $C0..$C1, $C8..$C9, $D6, $F1:met('???_?'); end; end; procedure affiche_debut_de_ligne; var l_pt_commentaire: t_pt_commentaire; l_commentaire: string127; begin writeln(sortie); if b_avec_octets_hexadecimaux then write(sortie, f_entier_hexadecimal(adresse_debut_ligne), ' '); l_pt_commentaire:= racine_commentaire; while l_pt_commentaire<> nil do begin cherche_commentaire(adresse_debut_ligne, 'D', l_pt_commentaire, l_commentaire); if l_commentaire<> '' then begin if b_avec_octets_hexadecimaux then write(sortie, '': 22); writeln(sortie, l_commentaire); if b_avec_octets_hexadecimaux then write(sortie, f_entier_hexadecimal(adresse_debut_ligne), ' '); end; end; l_pt_commentaire:= racine_commentaire; while l_pt_commentaire<> nil do begin cherche_commentaire(adresse_debut_ligne, 'M', l_pt_commentaire, l_commentaire); if l_commentaire<> '' then begin if b_avec_octets_hexadecimaux then write(sortie, '': 22); if nom_debut_ligne[1]<> ' ' then begin write(sortie, nom_debut_ligne); nom_debut_ligne:= ' '; end else write(sortie, '': 15); writeln(sortie, ' ', l_commentaire); if b_avec_octets_hexadecimaux then write(sortie, f_entier_hexadecimal(adresse_debut_ligne), ' '); end; end; end; procedure affiche_instruction; var l_indice: integer; l_pt_commentaire: t_pt_commentaire; l_commentaire: string127; begin if b_avec_octets_hexadecimaux then begin for l_indice:= adresse- adresse_debut_ligne to 7 do write(sortie, ' '); write(sortie, ' ', numero_ligne:4, ' '); end; write(sortie, nom_debut_ligne, ' ', l_ligne); l_pt_commentaire:= racine_commentaire; while l_pt_commentaire<> nil do begin cherche_commentaire(adresse_debut_ligne, 'F', l_pt_commentaire, l_commentaire); if l_commentaire<> '' then write(sortie, l_commentaire); end; if (l_code_operation in [$C2, $C3, $CA, $CB, $E9, $EA, $EB, $CF]) or ((l_code_operation in [$FE..$FF]) and ((l_code_operation and $38)<> 0)) then writeln(sortie); end; begin adresse:= p_adresse_debut; l_al_precedent:= 0; l_ah_precedent:= 0; l_ax_precedent:= 0; l_bl_precedent:= 0; l_bh_precedent:= 0; l_bx_precedent:= 0; l_cl_precedent:= 0; l_ch_precedent:= 0; l_cx_precedent:= 0; l_dl_precedent:= 0; l_dh_precedent:= 0; l_dx_precedent:= 0; while adresse<= p_adresse_fin do begin l_ligne:= ''; adresse_debut_ligne:= adresse; nom_debut_ligne:= f_label_debut_ligne(adresse); affiche_debut_de_ligne; lis_octet_suivant(l_code_operation); decode_instruction; affiche_instruction; numero_ligne:= numero_ligne+ 1; if b_stop_ecran and (numero_ligne mod 20= 0) then begin read(kbd, choix1); writeln(choix1); if upcase(choix1)= 'Q' then adresse:= adresse_fin+ 1; end; end; writeln(sortie); if p_adresse_fin+ 1- adresse<> 0 then begin writeln; write('dernier octet d‚sassembl‚: ', f_entier_hexadecimal(adresse- 1)); writeln(' <> adresse fin: ', f_entier_hexadecimal(p_adresse_fin)); end; end;