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

cs_parki 77 Messages postés mardi 29 juillet 2008Date d'inscription 20 mars 2014 Dernière intervention - 13 janv. 2013 à 15:57 - Dernière réponse : cs_parki 77 Messages postés mardi 29 juillet 2008Date d'inscription 20 mars 2014 Dernière intervention
- 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

Répondre au sujet
cs_parki 77 Messages postés mardi 29 juillet 2008Date d'inscription 20 mars 2014 Dernière intervention - 15 janv. 2013 à 12:48
+3
Utile
MERCI BruNews,ça marche enfin.
Et effectivement,j'ai encore beaucoup de choses
à apprendre,mais c'est cela qui me motive.

Bonne Prog.
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_parki
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 14 janv. 2013 à 18:08
0
Utile
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
cs_parki 77 Messages postés mardi 29 juillet 2008Date d'inscription 20 mars 2014 Dernière intervention - 14 janv. 2013 à 22:32
0
Utile
à 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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 15 janv. 2013 à 11:20
0
Utile
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
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 15 janv. 2013 à 13:00
0
Utile
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
cs_parki 77 Messages postés mardi 29 juillet 2008Date d'inscription 20 mars 2014 Dernière intervention - 16 janv. 2013 à 10:00
0
Utile
Merci pour l'info.
Commenter la réponse de cs_parki

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.