@Djes
Citation:
Ce n'est pas tout à fait vrai, FASM comme tout assembleur peut créer des fichiers objet (aucun rapport avec la POO) parfaitement compatibles avec n'importe quel OS puisque simplement en langage machine "pur" ; ces fichiers peuvent ensuite être utilisés pour créer un exe ou un elf grâce à l'édition de liens, ou un code de boot, ou autre chose.
Oui mais ce n'est pas le sujet, et cela dépends aussi du compilateur, un fichier objet est dès fois pas compatible d'un même compilateur d'une version a l'autre, quand à l'utilisé d'un OS à un autre, cela dépends du compilateur.
Citation:
Tout ça simplement pour dire qu'il est parfaitement possible d'intégrer un code à un EXE, si l'on sait soit travailler en relatif et se passer de variables, soit modifier les entêtes de l'EXE. C'est ce que font certains virus ou certains packers.
Oui, je l'ai déjà fait, c'est du bricolage, mais on ne balance pas du code ASM brut dans un exe "exesquelette" , c'est plus compliqué que cela.
Citation:
Pour ce qui est des différents "MOV", ils viennent du fait que FASM est un assembleur un peu amélioré et qu'il n'utilise pas un assembleur "pur" : il facilite la vie du programmeur avec une syntaxe un peu plus simple et du coup, le code résultant n'est pas toujours le même que celui que l'on a prévu. Mais en programmant en assembleur "officiel", un MOV reste un MOV, et le restera sauf si le chargeur ou un "optimisateur" passe par là

La dessus je ne suis pas d'accord, pour toi un MOV reste un MOV , dans ton code on est d'accord, mais le processeur lui non, en fonctions de différente opérande
pour le MOV , il peut prendre plusieurs valeur , prend cet exemple qui démontre ce que je te dis :
Citation:
!mov ax,0x65
!mov ax,bx
fait un exe et désassemble le.
le premier MOV vaut 0xB8, le second 0x89, conforment au datasheet d'un x86 :
http://ref.x86asm.net/coder32.html#x66Citation:
le code résultant n'est pas toujours le même que celui que l'on a prévu
Le code ci dessus est exactement le même dans l'exe final, rien ne change.
ps: j'ai fait un compilateur ASM pour PIC , donc je connais bien cette partie

@Zorro
Citation:
donc ton bytecode , n'as pas a etre interprété , c'est pas lui le langage
C'est la ton incompréhension , au contraire, un bytecode
EST la représentation de ton langage en
instruction simple et élémentaire que tu as choisi ( ADD MUL PUSH POP , etc... ) tu peut à partir de lui, soit le compilé directement ( plus dur car il faut bien connaitre le format cible PE/ELF,etc... ) pour faire un exe, soit l'interprété dans une machine virtuelle , soit le traduire ( comme le fait PB ) dans un autre langage.
Un byte code , c'est juste en PB :
list ByteCode.a() , c'est quand même mieux et plus rapide de traité un bytecode
préalablement vérifié
que de parser des strings a la volée...
Citation:
rappel un interpreteur c'est un prg qui "interprete" les mots d'un langage pour effectuer une action !
Oui, mais tes mots sont transformé en byte code, c'est pas une question de norme , mais de bon sens.
Citation:
toi en réalité tu as 2 verif de syntaxe a faire
celle du langage maison pour en faire un Bytecode
celle de ton byte code pour en faire un langage connu
Non, encore une fois , tu n'as rien compris. en gros :
- Tu vide ton code source des commentaires
- Tu sépares et sauvegarde chaque mot , chaque mot sauvegardé contient sa ligne dans le code, son fichier
ce qui donne en PB :
Code:
structure Token
rawCode.s
line.l
file.s
type.l
endstructure
- je passe le traitement preproc, include, macro, etc...
A la fin , tu as donc une liste de mots ( Token ) avec dedans pour chacun un type inconnu
- Tu identifie tout les mots ( c'est une variable ? une structure ? un opérateur ? un nombre ? un string ? etc ? )
- Tout dois être identifié parfaitement
- si tu as un type inconnu a la fin , tu génère une erreur propre , vu que tu as sauvegardé la ligne & le fichier dans le mot
- dans le cas d'une variable a déclaré, tu tombe sur un mot qui représente une variable "Toto.l"
- tu regardes si la variable est déjà déclarée ( dans une simple table des variable , avec une map par ex ) ( je ne parle pas de la portée , un simple arbre suffit à géré cela, la racine à la portée globale , les branches les portée locale, chaque branche possède ses tables de variables )
- si elle est déjà déclaré , rebelote , tu génère une erreur.
- sinon tu l'ajoute a la table des variable en fonction du scope
- pareil pour tout le reste
Ensuite si ta liste ne contient plus de token non identifié , tu passe à la suite, il faut généré le byte code a partir de la liste des tokens
en prenant en compte les subtilités
par exemple :
if A = 5 ou
A = 5 le '=' n'aura pas le même opcode, car il ne fait pas la même chose , d'un coté un test, de l'autre une affectation
une fois que ton byte code est généré , il faut faire une analyse sémantique de ton byte code , voir si il est bien formé
par exemple disont que le code suivant génère une erreur :
en PB :
if A === 5
avec un opcode maison :
OPERATOR_IF
VARIABLE
OPERATOR_EQUAL
OPERATOR_EQUAL
OPERATOR_EQUAL
VALUE
Arrivé au premier OPERATOR_EQUAL , ton "compilateur" s'attend pour la prochaine instruction a avoir ( selon ton langage ) soit une valeur , une fonction , mais pas un autre operateur.
Les régles de sémantique sont quand même plus simple a traité comme cela qu'avec des strings a la volée !
en PB ca donnerais ce genre de chose :
Code:
If opcode(index) = #OPERATOR
If opcode(index+1) <> #OPERATOR_FUNCTION Or opcode(index+1) <> #VALUE
; Erreur de syntaxe !
EndIf
EndIf
c'est quand même plus propre est moins brainfuck qu'une série de Stringfield() Ucase() Lcase() Mid()....
Citation:
et que chaque opérandes, opcode, a une certaine identité Hexadecimal, qui reste constante .
Non, c'est pas constant !
http://ref.x86asm.net/coder32.html#x66MOV, AND et d'autres change en fonctions des opérandes , c'est ce que j'expliquais à Djes.