Win3x.Org

Windows & DOS Community

Version bridée de macro-assembleur ?

Répondre   Page 2 sur 2  [ 11 messages ]
Aller sur la page « 1 2
Auteur Message
gm86
Sujet du message : Re: Version bridée de macro-assembleur ?
Publié : 03 mars 2020 13:56
Membre inscrit
Avatar de l’utilisateur
Hors-ligne
 
Messages : 630
Inscription : 01 sept. 2008 19:07
 
Nouvelle remontée.

En ce moment, je bidouille le format EXE. Le mot 12h d'un en-tête EXE (format MZ pour DOS) comporte le complément à un du checksum : cela signifie que l'addition sans retenue de tous les mots du fichier EXE (en-tête compris) donne FFFFh. Pour l'obtenir, LINK calcule d'abord le checksum avec le mot 12h nul :
http://bytepointer.com/download.php?nam ... xe_com.pdf
http://www.tavi.co.uk/phobos/exeformat.html
Je vais infirmer une de mes vieilles suppostions :
Citation :
- l'équipe Microsoft pour IBM ne savait pas quelle désignation donner à la directive !
Il est très simple de la faire avec le fichier ASM.EXE car son contenu tient dans un segment de mémoire. Il faut d'abord supprimer l'extension EXE pour forcer DEBUG à le charger comme un fichier binaire :
ren ASM.EXE *.
Il faut ensuite créer un le fichier texte ASM.TXT qui permettra de vérifier que l'ajout de la directive 286P, au bon endroit, renverra une somme de contrôle correcte (FFFFh) :
ad000
 xor dx,dx
 cld
 mov si,100
 lodsw
 add dx,ax
 dec cx
 loop d006

e999b '286P'
rip
d000
gd00c
q
- Fin -
Lors du chargement par DEBUG, la taille du fichier ASM est noté dans BX:CX (BX nul et CX < D000h - 100h dans le cas présent) :
debug asm < asm.txt
DEBUG obtient bien FFFFh dans DX !

Nous en déduisons que Microsoft a supprimé a posteriori la directive 286P, certainement pour mettre en avant sa version 3.00 par rapport à IBM :
http://bytepointer.com/masm/index.htm#MASM_3.0
D'ailleurs, heureusement que le DOS ne faisait pas usage de la somme de contrôle. Les fichiers ASM.EXE et MASM.EXE en version 2.00 (IBM) étaient théoriquement invalides. Il aurait été plus sage de remettre un mot nul à l'offset 12h de l'en-tête EXE :
http://www.fysnet.net/exehdr.htm


Samedi 7 mars

Avec le temps, même Microsoft préféra laisser un mot nul à l'offset 12h. Dans les cas contraire, le complément à un de la nouvelle somme de contrôle donnera zéro (NOT FFFFh) si le fichier EXE n'est pas altéré.

Voici un programme en QBasic pour MASM.EXE :
M$ = "Somme de contrôle correcte."
C$ = "Nouvelle somme de contrôle..."
E$ = "Mauvaise somme de contrôle !"
FICHIER$ = "MASM.EXE"
OPEN FICHIER$ FOR BINARY AS #1
IF LOF(1) = 0 THEN CLOSE : KILL FICHIER$: PRINT FICHIER$; " absent !": SYSTEM

FOR OCTET& = 1 TO LOF(1) STEP 2
        GET #1, OCTET&, MOT%
        IF OCTET& = &H13 THEN CONTROLE% = MOT%                  'Offset 12h
        LET SOMME& = (SOMME& + MOT%) AND &HFFFF&
NEXT

SOMME% = NOT VAL("&H" + HEX$(SOMME&))
IF SOMME% THEN IF CONTROLE% = 0 THEN PUT #1, &H13, SOMME%: M$ = C$ ELSE M$ = E$
PRINT M$
PRINT "NOT Checksum : "; HEX$(SOMME%); " ("; FICHIER$; ")"
SYSTEM
On découvre avec une erreur de calcul dans MASM 3 :
A>QBASIC /RUN CHECKSUM
Mauvaise somme de contrôle !
NOT Checksum : 100 (MASM.EXE)
Pour information, le mot suivant le nom complet des assembleurs IBM contient le mot 1. Il permet l'affichage du copyright IBM. Quant à MASM 3, il s'agit du mot précédant le nom. Mais il est à zéro vu qu'il ne s'agit pas d'une version OEM.


Lundi 9 mars

Bug de l'encodage de l'instruction 186 PUSH imm. remarqué par Charles Petzold :
http://books.google.fr/books?id=FC-L2faxEVkC&pg=PA326
http://books.google.fr/books?id=-9qzy8Z ... VQR&pg=292
Dans les versions 2.0 et 3.0 de MASM, l'instruction ADD AX,68h entre en jeu.

Après pistage de la valeur 1234h (test d'assemblage de PUSH 1234h) grâce à DEBUG et au désassemblage de MASM 2.0, je suis tombé sur le code incriminé en SEG+15h:3762h.


Samedi 14 mars

ASM.EXE, qui ne gère aucun code autre que 8086, incorpore pourtant la portion qui teste la suffisance d'un octet signé pour stocker un mot. Bien qu'elle soit utilisée, elle ne cause pas de bug à l'instruction CPM reg16≠AX,imm.

Par contre, il n'y a plus de test pour savoir si on a affaire à l'instruction PUSH imm., inexistante pour le 8086. On le voit en comparant le code en CS+124h:4FF5h avec celui de MASM 2.0 en CS+125h:5D34h. La valeur immédiate, d'une longueur d'un octet dans le pire des cas, est traduite en offset sans émettre de message d'erreur.


Le surlendemain

On remarque que l'instruction fictive POP imm. est malencontreusement traduite en PUSH imm. par MASM.


Jeudi 19 mars

À en croire Roger Schlafly, d'anciennement Borland International, l'option /ML apportée par MASM 3.0 altère la traduction d'une instruction 8087 écrite en minuscules.


Les lendemain et surlendemain

Je voulais m'attaquer au message manquant que pointait Roger Schlafly. C'est un problème commun à MASM 2.0, évidemment. Lorsque deux opérandes ST suivent une instruction 8087, MASM ignore le fait que l'un des deux ne soit pas le numéro zéro. Au lieu d'émettre un message d'erreur, il suppose que le deuxième est ST(0). MASM 5, lui, signale "error A2052: Improper operand type" comme lorsque l'opérande n'est pas un registre.

On peut traquer la gestion d'erreur, dans MASM 2.0, en en provoquant une. Il n'existe pas de registre ST dont le numéro va au-delà de 7. D'ailleurs, un éventuel signe moins provoquera aussi une "50:Value is out of range" à la deuxième passe.

En temps normal, le test remplace la valeur du premier opérande par le second. Il y en a forcément un de nul en absence de faute. Cela n'interfère pas avec les instructions 8087 n'ayant qu'un seul opérande : MASM met préalablement à zéro la destination.

Revenant au problème particulier de MASM 3.0, l'assembleur s'attend à ce que la deuxième lettre de l'instruction FLD soit une majuscule (comparaison en CS+125:50F3). D'où ce stupide bug qui demeure dans MASM/2.

Lundi 30 mars

Au retour de cette routine, on remarque que MASM a déjà traité l'instruction et qu'il n'a besoin de connaître que le numéro du registre autre que zéro. C'est pourquoi FMUL ST(n),ST(x) devient FMUL ST(n),ST. En intervenant ici, on laisserait le soin à l'erreur "63:Operand combination illegal", qui apparaît lorsque le dernier opérande des instructions 8087 à suffixe P n'est pas ST(0), d'être traitée ailleurs : FADDP ST(n),ST est par exemple valide.

Toutefois, on en reste là. Comme avec le bug commenté par Microsoft à propos de DUP (offset Variable) qui existe encore dans MASM 3.0 : DUP (Variable) évite que LINK signale une erreur voire, avec une version récente, remplace la valeur à répéter par zéro.


Dimanche 5 avril

Les fonctions de conversion numérique de la bibliothèque IBMUTIL.LIB sont expliquées dans l'ouvrage L'Assembler per l'80286/80386 :
$18_1NPUT	da stringhe ASCII a 80287/80387
$18_0UTPUT	da long real 80287/80387 a stringhe ASCII
$14_M4		da Microsoft singola a short real 80287/80387
$18_M8		da Microsoft doppia a long real 80287/80387
$M4_14		da short real 80287/80387 a Microsoft in singola precisione
$M8_18		da long real 80287/80387 a Microsoft in doppia precisione
$14_18		da long real 80287/80387 a short real 80287/80387
$18_14		da short real 80287/80387 a long real 80287/80387


1. Il segmento di codice deve essere dichiarato in questo modo:

CODMAT	SEGMENT	BYTE	PUBLIC	'CODE'
	EXTRN	$18_0UTPUT:NEAR

(Qui di seguito si inserisce il contenuto del segmento di codice)

CODMAT	ENDS

2. Il segmento dati viene dichiarato in questo modo:

DATI	SEGMENT	WORD	PUBLIC	'DATI'

(Qui di seguito si inserisce il contenuto del segmento di dati)

DATA	ENDS
DGROUP GROUP DATI

3. Tutte le routine sono procedure di tipo NEAR.

4. I registri DS e ES sono uguali.

5. Il contenuto di tutti i registri che non sono registri di segmento (ad eccezione
di SP) viene alterato.

6. SI:DS punta all'indirizzo (offset) del numero di tipo long real prima che
la routine venga chiamata.

7. Dopo l'esecuzione della routine, SI:DS punta all'indirizzo (offset) di
LSTRING. Questa è una locazione di memoria di 17 byte che contiene,
nel primo byte, la lunghezza della stringa ASCII prodotta. La virgola decimale
è a sinistra.

8. AX contiene il valore 1 se è stato utilizzato il numero originale, e il valore
0 se il numero da convertire era indefinito.

9. BL contiene un carattere spazio nel caso di numero positivo e una lineetta
nel caso di numero negativo.

10. DX contiene l'esponente del numero espresso nel formato in base 10.
Samedi 2 mai

L'indicateur du code en CS+125h:3762h est bon. Il renseigne les instructions SAR, SHL & SHR du 80186 que la valeur immédiate tient dans un entier 8 bits non signé. Le code en CS+125h:6785h de l'instruction CPM reg16≠AX,imm le remplace par l'inverse de l'indicateur précédent :
mov	ax,[si+0Dh]
xor	al,1
mov	[si+0Ch],al
C'est ce qui manque au code de l'instruction PUSH imm pour savoir si un entier 8 bits signé suffisait. De même, hélas, pour IMUL reg[,reg],imm.


Dimanche 17 mai (pile mise à jour à l'Armistice)

Le macro assembleur Microsoft.

SID de Digital Research accepte l'écriture de fichiers EXE, ainsi que l'arithmétique des segments de mémoire.

Microsoft MASM 1.27 avec correction du format LST en 80 colonnes (Page Symbols-1 sur une seule ligne) et du bug de l'an 2000 :
SID86
rMASM.EXE
sw2
174
.
swA
82
.
sw10
800
0
.
sw1014
BB
.
sw1018
CA
.
sw101C
D9
.
sw1020
DF
.
sDS+10A9:1C25
20
.
mCS+13C5:B1,+70,130
mCS+13C5:130,+70,B3
aCS+13C5:A9
mov    cx,#100
MOV    ax,[1E]
xor    dx,dx
div    cx

wMASM.EXE
q
NOT Checksum = EEACh :
A>QBASIC /RUN CHECKSUM
Nouvelle somme de contrôle...
NOT Checksum : EEAC (MASM.EXE)

A>QBASIC /RUN CHECKSUM
Somme de contrôle correcte.
NOT Checksum : 0 (MASM.EXE)
MASM 1.27 ne renvoie pas d'errorlevel (DOS 2 ou plus) s'il y a une erreur sévère.

L'assembleur IBM.

DEBUG returne la taille du fichier binaire dans les registres BX:CX, avec BX nul s'il tient dans un seul segment de mémoire.

IBM ASM 2.00 avec rétablissement de l'erreur PUSH imm (8086)--ainsi que du code d'erreur 52 pour SAL/SAR/SHL/SHR reg,|imm|≠1 au lieu de 50--et correction du bug de l'an 2000 :
REN ASM.EXE *.
DEBUG ASM
mCC62 CCD5 CC66
aCC5B
mov     cx,64
MOV     AX,[1C]
db      33 D2
div     cx
push    dx

e10A 81
e110 00 8 0 0
eC3A AD
eC3E BC
eC42 CB
eC46 D1
e5C45 34
e999B '286P'
eB9C2 F4
a80
add word[102],4
add cx,4
push cx
mov si,100
cld
lodsw
add dx,ax
dec cx
loop 8D
not dx
mov [112],dx
pop cx
nop

g=80 9B
w
q
REN ASM *.EXE
NOT Checksum = B889h :
-g80 9B

AX=0000  BX=0000  CX=CBDA  DX=B889  SP=FFEE  BP=0000  SI=CCDA  DI=0000
ASM 2.00 renvoie un errorlevel 1 (DOS 2 ou plus) s'il y a une erreur sévère.

Ajout du 7 novembre : IBM MASM 2, MS MASM 3 et suivants signalent une valeur immédiate supérieure à 255 par l'erreur 50:Value is out of range. Malencontreusement, IBM ASM 2 l'utilise à la place de 52:Improper operand type pour un opérateur autre que |imm|=1 ou CL. D'où une nouvelle ligne au patch.


Mardi 10 novembre

Les premières versions de MASM débutaient avec une pile de 20 octets sans allocation requise (SP=14h & MIN-ALLOC=0). De plus, le lancement calculait une nouvelle pile en arithmétique signée. Ce qui fausse le résultat à partir de 512 Ko de mémoire allouable aux données :
http://www.os2museum.com/wp/pascal-out-of-memory/

MASM 1.25 étant compilé avec une autre version de PASCAL, le problème semble résolu : une pile de 128 octets est fixée dans une zone allouée (SP=80h & MIN-ALLOC={8;9;Ah}) et l'arithmétique pour en calculer une nouvelle est non signée. Toutefois, CREF reste compilé à l'ancienne.

Finalement, il s'est révélé que seuls MASM & CREF 3.0 étaient fiables de cette manière. Les versions précédentes continuant à se planter si la mémoire était un peu juste. C'est pourquoi il aurait été préférable d'allouer la pile de 2 Ko du compilateur PASCAL, donc de la pointer à l'offset 10h de l'en-tête EXE et d'indiquer l'équivalent en paragraphes supplémentaires à l'offset Ah : SP=800h & MIN-ALLOC={80h;81h;82h}. En outre, c'est ce que LINK /STACK:2048 imposerait sachant qu'une taille quelque supérieure sera fixée au lancement de MASM ou d'ASM (IBM).

Nous remarquons que la fin de MASM 1.27 comble le dernier paragraphe par des valeurs non initialisées (déduites de la taille), alors qu'ASM 2.00 voit sa chaîne finale suivie par seize octets plus un initialisés à zéro. Notre correction du bug de l'an 2000 repousse la fin de fichier telle qu'elle est notée dans l'en-tête EXE (taille modulo 512 à l'offset 2) : deux octets pour MASM et quatre pour ASM.

P.S. : nouveau confinement, nouveau bidouillage.
Format EXE :
  00h	MZ sinon ZM
  02h	Longueur du fichier modulo 512
  04h	Taille du fichier en nombre de pages
  06h	Nombre de relogements
  08h	Taille de l'en-tête en paragraphes
  0Ah	MIN-ALLOC en paragraphes
  0Ch	MAX-ALLOC (altérable par LINK /CPARMAXALLOC)
  0Eh	Déplacement du segment de pile par rapport au programme
  10h	SP à l'entrée (altérable par LINK /STACK)
  12h	Complément à un du checksum 16 bits sinon 0
  14h	IP à l'entrée
  16h	Déplacement du segment de code par rapport au PSP
  18h	Offset du premier relogement
  1Ah	Numéro d'overlay (0 si partie résidente)
  1Bh	Espace réservé (taille variable)
  ...	Table de relogement
  ...	Espace réservé (taille variable)
  ...	Segments de code et de données
  ...	Segment de pile
Il est prévu de mettre le partie débutant mi-mai dans la section Projets.

Ajout du vendredi 27/11 :
ASM 2.00
SMALL.BAT :
REN ASM.EXE *.BAK
IF EXIST ASM.EXE ERASE ASM.EXE
COPY ASM.BAK *.BIN
DEBUG ASM.BIN<SMALL.TXT
REN ASM.BIN *.EXE
SMALL.TXT :
mCC62 CCD5 CC66
aCC5B
mov     cx,64
MOV     AX,[1C]
db      33 D2
div     cx
push    dx

e102 DA 1
e10A 81
e110 00 8 0 0
eC3A AD
eC3E BC
eC42 CB
eC46 D1
e5C45 34
e999B '286P'
eB9C2 F4
a80
add cx,4
push cx
mov si,100
add si,cx
mov [si],bh
sub si,cx
inc cx
shr cx,1
lodsw
add dx,ax
loop 90
not dx
mov [112],dx
pop cx
ret

g=80 9C
w
q
MASM 1.27
MACRO.BAT :
REN MASM.EXE *.BAK
COPY MASM.BAK *.EXE
SID<MACRO.TXT
MACRO.TXT
a100
mov ax,ds
add ax,14
mov ds,ax
mov es,ax
mov bx,[4]
inc ch
xor si,si
dec bx
jnz 11E
es:mov cx,[2]
jcxz 11E
inc cx
shr cx,1
lodsw
add dx,ax
loop 11E
mov ax,ds
add ax,20
mov ds,ax
or bx,bx
jnz 10D
not dx
es:mov [12],dx
nop

rMASM.EXE,ES+14:0
sw2
174
.
swA
82
.
sw10
800
0
.
sw1014
BB
.
sw1018
CA
.
sw101C
D9
.
sw1020
DF
.
sDS+14+10A9:1C25
20
.
mCS+14+13C5:B1,+70,130
mCS+14+13C5:130,+70,B3
aCS+14+13C5:A9
mov    cx,#100
MOV    ax,[1E]
xor    dx,dx
div    cx

xI
0
xSP
140
.
g,135
wMASM.EXE
xDX
.
q
NOP évite un plantage lors de l'affichage des registres (X sans option), bien qu'ici seul DX soit montré.
Infos de Microsoft sur MASM :
http://ftpmirror.your.org/pub/misc/ftp. ... R/MASM/KB/

_________________

C:\ONGRTLNS.W95


Haut
Profil
Afficher : Trier par : Ordre :
Répondre   Page 2 sur 2  [ 11 messages ]
Revenir à « Documentations et tutoriels » | Aller sur la page « 1 2
Aller :