Analyse des 6 volumes OCRisés (Resources/coeur-tp-ocr/coeur-tp-*-d.txt)
pour le projet TP3-comp (compilateur Turbo Pascal 3 → 8086 asm).
OCR français (tesseract -l fra --psm 3), reconstruit à partir des colonnes
opcode/adresse (OCR fréquemment faux : :=→\:=, *→\, instruction MOT). Ne vous
fiez jamais au champ mnémonique seul — recalculez depuis les octets.
coeur-tp-1-d.txt, 19 p.) : couverture / plan.-02 26 p., -03 29 p.) : ch.4 IMPLÉMENTATION DES TYPES.-04 46 p.) : ch.5 LE CODE COMPILE (5.1-5.5).-05 42 p.) : ch.5 suite (5.5-5.7 + synthèse 5.A).-06 59 p.) : ch.6 LES OPTIONS DE COMPILATION + début ch.7 LA LIBRAIRIE.Total vérifié : 221 pages. Seuls les fichiers *_d.txt sont valides (les autres
ont été supprimés).
READLN d'un entier > MAXINT → erreur runtime 10.CHAR : 1 octet, ASCII étendu (0..255).BOOLEAN : 1 octet, FALSE = 0, TRUE = bit 0.$41 $00 $00 $00 $00 $75 $93 $48.V- : désactive la vérification (débordement) des chaînes.NEW réserve la place + bourrage à un multiple de 8.NEW(n, selecteur) : non implanté.FILE (blocs) : BLOCKREAD/BLOCKWRITE.$0D $0A ; EOF = CTRL-Z $1A ;
les fichiers TEXT n'ajoutent pas de $1A final.2D4D E849DD call TU_PARAGRAPHS
2D50 0600 hex 0600 ; options
2D52 .... hex .... ; cs
2D54 .... hex .... ; ds
2D56 .... hex .... ; code
2D58 .... hex .... ; globales
2D5A .... hex .... ; min piles
2D5C .... hex .... ; max piles
2D5E .... hex .... ; fichiers
2D60 .... hex .... ; input
2D62 .... hex .... ; output
2D64 8BEC mov bp, sp
2D66 E814DF call TU_TAILLE_CODE
2D69 .... hex .... ; taille du code
2D6B .... adr SAUT_PRINCIPAL
2D6D E9xxxx SAUT_PRINCIPAL jmp PRINCIPAL
; ... ici : procédures + constantes typées ...
PRINCIPAL:
; ... code du programme ...
jmp FIN
; ... relais GOTO hors FOR : RELAI_GOTO_n: pop ax; jmp cible ...
FIN:
xor ax, ax
call TU_HALT
hex 0000
l'adresse de retour PUSH du CALL : octet faible poussé d'abord, SP diminue de 2.RET dépile dans le compteur de programme (PC).| Pascal | 8086 généré |
|---|---|
a * b |
mov ax,a ; mov cx,const ; imul cx |
a DIV b |
... ; cwd ; idiv cx |
a MOD b |
... ; idiv cx ; xchg dx,ax |
SQR(x) |
mov ax,x ; imul ax |
SUCC(x) |
inc ax |
PRED(x) |
dec ax |
push ax / pop cx). Exemple :mov ax, $11
mov cx, $22
imul cx
push ax
mov ax, $33
push ax
mov ax, $44
add ax, $55
pop cx
imul cx
pop cx
add ax, cx
Résultat calculé dans AX (1 pour vrai, 0 pour faux) :
mov ax, $0001
Jcc saute ; Jcc = je/jg/jnle/jnl/jl/jle/jnz selon l'opérateur
dec ax
saute:
; avec R+ :
mov cx, $0000
mov dx, $0001
call TU_RANGE_CHECK ; bornes dans CX,DX
mov [var], al ; booléen = 1 octet
mov ax,[$0262] (première globale = $0262).mov [addr], ax / mov [addr], al.les di,[bp+$FC]).mov ax, var
cmp ax, imm
je THEN1
jmp FIN_IF1
THEN1: ; ... corps ...
FIN_IF1:
IF/ELSE :
je THEN2
jmp ELSE2
THEN2: ; ... corps THEN ...
jmp FIN_IF2
ELSE2: ; ... corps ELSE ...
FIN_IF2:
IF TRUE THEN ; → mov ax,$0001 ; or ax,ax ; jnz ....cmp ax,label ; je cas_n ; jmp test_suivant.cmp ax,lo ; jl suivant ; cmp ax,hi ; jle cas_n.cmp ax,$AAAA ; je cas.jmp FIN_CASE.JMP_S.DEBUT_REPEAT:
; ... corps ...
; ... évaluation condition ...
jxx FIN_REPEAT
jmp DEBUT_REPEAT ; retour arrière toujours en JMP long
FIN_REPEAT:
teste_while:
; ... évaluation condition ...
Jxx debut_while
JMP fin_while
debut_while:
; ... instruction ...
JMP teste_while
fin_while:
Calcul des bornes (la 1re borne est push ax pour ne pas être écrasée par l'expression
de la 2e ; pop cx ; xchg cx,ax ; sub cx,ax) :
jnl ENTRE_FOR
jmp FIN_FOR
ENTRE_FOR:
inc cx
mov [compteur], valeur_initiale
boucle_for:
push cx
; ... corps ...
pop cx
dec cx
je FIN_FOR
inc word [compteur]
jmp boucle_for
FIN_FOR:
DOWNTO : miroir (décrément).GOTO vers l'intérieur d'un corps de FOR : interdit (CX ne serait pas sauvegardé).GOTO/EXIT hors d'un FOR : nécessite un relais spécial pour dépiler CX
(RELAI_GOTO_n: pop ax ; jmp cible).Procédure au premier niveau :
X: push bp ; BP de l'appelant
mov bp, sp
push bp ; "valeur de BP actuelle"
jmp DEBUT_X
DEBUT_X: sub sp, $03 ; zone variable(s) (3 octets ici)
...
FIN_X: mov sp, bp
pop bp
ret ; (ret imm si paramètres, voir 3.11)
Procédure imbriquée (table des accès) :
T: push bp
mov ax, sp
push [bp+$FE] ; recopie la table de l'englobante (BP)
mov bp, ax
push bp
jmp DEBUT_T
Imbrication à n niveaux : re-push des entrées [bp+$FE], [bp+$FC], ... (chaque
niveau : sauter 2 octets de plus). [bp+$FE] pour la 1re visite ; +2 par niveau
supplémentaire.
Accès aux variables locales/paramètres : via BP (mov [bp+$FC],ax, etc.).
Accès aux variables de l'englobante (intermédiaires) via la table :
mov bx, [bp+$FE] ; BP de la procédure englobante
seg ss
mov ax, [bx+$FC] ; variable de l'englobante
Pile d'une procédure (SP → adresses hautes) :
la dernière variable locale <--- SP
la deuxième variable locale
la première variable locale
la valeur de BP actuelle
la valeur de BP de la procédure englobante
la valeur de BP de la première procédure
la valeur de BP de l'appelant <--- BP
l'adresse de retour <--- BP+2
dernier paramètre
premier paramètre
Appel (les params sont poussés dans l'ordre des déclarations) :
mov cx, $0012 ; 6 environnement + taille des paramètres
call TU_STACK_CHECK ; TOUJOURS avant un appel avec zone
mov ax, $AAAA
push ax ; paramètre valeur
mov di, $0264
push ds
push di ; paramètre variable : SEG puis OFFSET
call DEUX
Accès dans le callee :
mov ax, [bp+$0E] ; 1er paramètre valeur (après 2 var + 1 valeur = $0E)
les di, [bp+$08] ; LES : ES:DI ← adresse segmentée du 1er paramètre variable
seg es
mov [di], ax
mov sp,bp ; pop bp ; ret imm — ret imm (c.-à-d. "intra") dégage
les paramètres (2 octets par paramètre valeur, 4 par paramètre variable).Fonction entière — résultat dans AX, zone résultat réservée par l'appelant :
; appelant :
mov cx, $0008 ; 6 environnement + 2 résultat
call TU_STACK_CHECK
dec sp ; réserve le résultat (2 octets)
dec sp
call F_FONCTION
mov [$0262], ax ; entier := f_entier
; callee :
mov ax, $0077
mov [bp+$04], ax ; affectation au nom de fonction → zone [BP+4]
mov ax, [bp+$04] ; AX ← résultat
mov sp, bp
pop bp
ret 0002 ; intra : dégage le résultat
Fonction chaîne — résultat laissé sur la pile, épilogue via la librairie :
DEBUT_F_CHAINE:
lea di, [bp+$04]
push ss
push di
call TU_POUSSE_K_ST ; pousse la constante chaîne
(03 ; longueur
asc 'ABC')
mov cl, $0B ; taille max (STRING[11])
call TU_POP_STRING
...
mov dx, $0000
mov cl, $0B
mov sp, bp
pop bp
jmp TU_RESU_FCT_ST ; le résultat reste sur la pile
; appelant :
mov di, $0262
push ds
push di ; seg:off de chaine (dest)
mov cx, $0012 ; 6 env + 12 résultat
call TU_STACK_CHECK
sub sp, $0C ; réserve le résultat (string)
call F_CHAINE
mov cl, $0B
call TU_POP_STRING
Résumé : résultat entier → AX ; résultat réel/chaîne → laissé sur la pile.
call TU_DEB_RW_DEFAUT ; call TU_WRITELN ; call TU_IO_CHECK
(idem : TU_READ_DEFAUT, TU_READ_ENTIER, TU_WRITE_ENTIER,
TU_WRITE_FICHI, TU_READ_FICHI, TU_CLOSE).xor ax,ax ; call TU_HALT.CONST nom : type = valeur ;. Modifiables comme des variables.seg cs sur les MOV, et pousse cs au lieu de ds
pour les routines de la librairie qui attendent un segment sur la pile.jmp PRINCIPAL.kt_entier $1711 → hex 1111 ; TRUE → 01 ; 'A' → 41 ;
1.75 → 6 octets.push cs / push di ; mov di,offset ; push ds ; call TU_POUSSE_REEL ;
call TU_POP_REEL_DI.seg cs sur le stockage ; WITH sur constante typée pousse CS.Quatre cas :
ABSOLUTE CSEG:$2D50 → traité comme constante typée.ABSOLUTE DSEG:$0242 → traité comme globale (offset fourni).ABSOLUTE autre_variable → traité selon le segment de l'autre (DS ou SS);
globale → DS, locale/paramètre → SS.ABSOLUTE $1234:$5678 → l'adresse (décalage puis segment, petits-boutistes) est
stockée dans le code et l'accès se fait par LES :2D70 7856 hex 7856 ; décalage $5678
2D72 3412 hex 3412 ; segment $1234
...
les di, [$2D70] ; ES:DI ← $1234:$5678
seg es
mov ax, [di]
Deux catégories de données :
Affectation : le calcul d'adresse peut être séparé du stockage ; adresses sauvegardées sur la pile. Fichiers : via librairie → DOS.
(*$...*) ou { $... } (pas d'espace entre l'ouvrant et $).I/R/K/V/U/C/B/D/F/G/P.R- : retire les contrôles d'intervalles (TU_RANGE_CHECK/TU_INDEX_CHECK non émis).I- : supprime la levée d'erreur d'entrée-sortie jusqu'à I+.V- : désactive la vérification des chaînes.(*$g512,p512,d-*) : exemple fixant nombre de fichiers = 512 ? et périphériques par défaut.min piles, max piles — mots du squelette §3.1).TU_* des routines runtime (TU_PARAGRAPHS, TU_TAILLE_CODE, TU_HALT,
TU_STACK_CHECK, TU_RANGE_CHECK, TU_INDEX_CHECK, TU_POUSSE_REEL, TU_POP_REEL_DI,
TU_POUSSE_K_ST, TU_POP_STRING, TU_RESU_FCT_ST, TU_DEB_RW_DEFAUT, TU_WRITELN,
TU_IO_CHECK, TU_READ_DEFAUT, TU_READ_ENTIER, TU_WRITE_ENTIER, TU_WRITE_FICHI,
TU_READ_FICHI, TU_CLOSE, ...). Détails complets dans coeur-tp-06-d.txt.File Paste: <pasteId>). Ne pas créer de
fichiers pour la référence elle-même.ASM pour le code ; les blocs (*$...*) sur des
lignes simples avec en-têtes de section style INI ; les options en ligne ((*$R-*))
en italique. Marqueur "OPTIONS INFO" pour les bascules d'options.types) ; le français pour les termes
propres au livre.((o)) / ((c))) : ré-émettre la section complète
corrigée ; ne pas prétendre avoir appliqué la correction si l'on ne sait pas qu'elle
a été appliquée (c'est l'utilisateur qui l'applique). AM + END = délimiteur de zone.-1, -02..-06), extraction de
ch.4 (types), ch.5 (code), ch.6 (options), ch.7 (début librairie).INIT_FOR avec constantes,
template UPTO/DOWNTO (contenant TU_SEG + TU_SUB_ALIGN), paramètres/fonctions
(5.7.6-5.7.7), constantes typées (5.8), variables absolues (5.9), synthèse 5.A.Resources/turbopascal3source/TP3/, TPSRC1-10) et le désassembleur
Resources/DESASS/ si besoin.Resources/coeur-tp-ocr/ — les 6 volumes OCRisés (source de cette référence).turbopascal3source/TP3/ (TPSRC1-10, MAIN) — source du compilateur TP3 (vérité).DESASS/ — désassembleur ; AS.COM / AS.PDF — assembleur.TP3/ — distribution TP3.The_Turbo_Pascal_Tutor_1985.pdf, Turbo_Pascal_Version_3.0_Reference_Manual_1985.pdf,
TURBO-LESSONS (Cours.md), Welsh_Hay (Model Implementation of Standard Pascal),
Disassembly of old Turbo Pascal (V3) code (Stack Overflow HTML), etc.