MASM et VISUAL C++ 2008 Express [Résolu]

Messages postés
78
Date d'inscription
mardi 29 juillet 2008
Statut
Membre
Dernière intervention
25 mars 2019
- - Dernière réponse : cs_parki
Messages postés
78
Date d'inscription
mardi 29 juillet 2008
Statut
Membre
Dernière intervention
25 mars 2019
- 16 janv. 2013 à 10:00
Bonjour,

je n'arrive pas créer un programme C++ utilisant un module .asm dans visual c++ 2008 express
Le prog est issu de l'aide Visual c++ (EuclidStep2).
voici ce que je fais;

1: creation d'un projet console vide win32
2: écriture du fichier "composantC.cpp" suivant;


#include <stdio.h>
#include <stdlib.h>

extern "C" {
/* fonction assembleur */
extern int _stdcall euclid(int,int);
}


void usage(char*);

int _cdecl main(int argc, char* argv[])
{
int i, j;

// prompt with usage if command line arguments are not present
if (argc<3)
usage(argv[0]);

// retrieve command line arguments
i = atoi(argv[1]);
j = atoi(argv[2]);

// prompt with usage if command line arguments are not non-zero,
// positive integers
if (!(i>0) || !(j>0)) {
printf("%s %d %d\n", argv[0], i, j);
usage(argv[0]);
}

// call function that implements Euclid's algorithm, in this case an
// assembly language function, and print result
printf("The greatest common divisor of %d and %d: %d\n", i, j, euclid(i, j));
return 0;
}

void usage(char* str)
{
printf("usage: %s num1 num2\n", str);
printf(" for non-zero, positive num1 and num2\n");
exit(1);
}


3 ecriture du fichier "copo.asm" suivant;

.586
.model flat, stdcall
option casemap :none
option prologue:none
option epilogue:none

.code

euclid PROC C x:SDWORD, y:SDWORD
mov ecx, x
mov eax, y
@@:
cmp ecx, eax
jge noswap
xchg eax, ecx
noswap:
sub ecx, eax
jnz @B
; return value already in eax
RET
euclid ENDP

end

4: configuration du projet;

règle de génération personnalisée=Microsoft Macro Assembleur
propiétées du fichier .asm / fichier objet/nom du fichier object=$(IntDir)\$(InputName).obj
ligne de commande/ Microsoft Macro Assembleur = ml.exe /c /nologo /Fo "debug\copo.obj" /W3 /Zi /errorReport:prompt copo.asm /Ta


5: quand je "génére la solution",mon .asm est bien assembler en .obj mais ensuite l'éditeur de liens
me sort le message suivant;

.\Debug\copo.obj : fatal error LNK1107: fichier non valide ou endommagé : impossible de lire à 0x1D9


Quand j'analyse le fichier coco.obj avec un editeur hexa,l'offset 0x1D9 correspond au dernier octet de données + 1
(le fichier .obj va de l'oofset 0 à 01D8).
je suis sous XP.

j'ai essayé avec un .obj produit séparément par MASM,ça ne marche pas non plus.
Qu'est ce qui ne va pas ?(l'aide en ligne de visual ne pas aidé)
Afficher la suite 

6 réponses

Meilleure réponse
Messages postés
78
Date d'inscription
mardi 29 juillet 2008
Statut
Membre
Dernière intervention
25 mars 2019
3
Merci
MERCI BruNews,ça marche enfin.
Et effectivement,j'ai encore beaucoup de choses
à apprendre,mais c'est cela qui me motive.

Bonne Prog.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 204 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_parki
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13
0
Merci
Du temps où j'utilisais VC++ (il ya un bail) et que je faisais de l'ASM 32 (encore plus vieux), je réglais ainsi la propriété de compil du fichier ASM:

ml.exe -c -coff -Cx /nologo -Fo$(IntDir)%(Filename).obj %(Filename).asm
$(IntDir)%(Filename).obj;%(Outputs)

ciao...
Commenter la réponse de BruNews
Messages postés
78
Date d'inscription
mardi 29 juillet 2008
Statut
Membre
Dernière intervention
25 mars 2019
0
Merci
à priori visual c++ 2008 ne comprend plus la macro (Filename),elle est remplacée par
$(InputName),j'ai donc modifié la ligne de commande de ml comme suit;

ml -c -coff -nologo -Cx "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"

et en sortie;

$(IntDir)\$(InputName).obj

et avec ces deux lignes j'ai maintenant le message d'erreur suivant;

1>composant C.obj : error LNK2019: symbole externe non résolu _euclid@8 référencé dans la fonction _main

???
Commenter la réponse de cs_parki
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13
0
Merci
Tu m'as fait compiler du 32 bits, merci pour ce retour au 20eme siècle.
Exemple testé fonctionnant.

FICHIER utils.asm

.586
.model flat, stdcall
option casemap :none
option prologue:none
option epilogue:none

_TEXT SEGMENT

; DWORD __stdcall bnEuclid(DWORD a, DWORD b)
bnEuclid PROC a:DWORD, b:DWORD
mov ecx, [esp + 4] ; a
mov eax, [esp + 8] ; b
nextPASS:
cmp ecx, eax
jae short noSWAP
mov edx, eax
mov eax, ecx
mov ecx, edx
noSWAP:
sub ecx, eax
jne short nextPASS
ret 8 ; ATTENTION QU'IL FAUT DEPILER !!!
bnEuclid ENDP

_TEXT ENDS

END
-----------------------------

FICHIER utils.h

#ifndef UTILS_H
#define UTILS_H

#ifdef __cplusplus
extern "C" {
#endif

DWORD __stdcall bnEuclid(DWORD a, DWORD b);

#ifdef __cplusplus
}
#endif

#endif
----------------------------

FICHIER C QUI TESTE:

#include <windows.h>
#include "utils.h"

char szappname[] = "tstEucld";

void tstEuclide()
{
char buf[16];
DWORD r;
r = bnEuclid(40, 35);
ultoa(r, buf, 10);
MessageBox(0, buf, szappname, 0);
}

#pragma comment(linker, "/entry:myWinMain")
void __fastcall myWinMain()
{
tstEuclide();
ExitProcess(0);
}
-------------------------

EXE fait 2.5 Ko et affiche bien 5 comme attendu.

CONSEILS:
Evite la syntaxe daube qu'on voit dans les exemples MS et ailleurs.
"mov ecx, x" NON !!! Ce x est en [esp + 4] alors tu l'écris sinon tu ne sauras jamais coder.
Le jour où tu voudras faire du x64, tu devras apprendre l'ASM que tu auras cru savoir.


ciao...
Commenter la réponse de BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13
0
Merci
J'ai oublié l'explicatio du pourquoi le linker dans ton code ne trouvait la fonction.

bnEuclid PROC a:DWORD, b:DWORD

le prog C appelle _bnEuclid@8, on parle habituellement de la "décoration" du nom.
Tu notes que je n'ai pas mis "bnEuclid PROC C" pour exporter correctement en stdcall, ml.exe fera donc "_bnEuclid@".
Ensuite "a:DWORD, b:DWORD" ne sert qu'à informer ml.exe de combien d'octets sont PUSHés afin qu'il ajoute le 8 (2 params en x86 = 8 octets) à la fin du nom.
Bonne continuation.

ciao...
Commenter la réponse de BruNews
Messages postés
78
Date d'inscription
mardi 29 juillet 2008
Statut
Membre
Dernière intervention
25 mars 2019
0
Merci
Merci pour l'info.
Commenter la réponse de cs_parki