MASM et VISUAL C++ 2008 Express

Résolu
cs_parki Messages postés 75 Date d'inscription mardi 29 juillet 2008 Statut Membre Dernière intervention 25 mars 2019 - 13 janv. 2013 à 15:57
cs_parki Messages postés 75 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é)

6 réponses

cs_parki Messages postés 75 Date d'inscription mardi 29 juillet 2008 Statut Membre Dernière intervention 25 mars 2019
15 janv. 2013 à 12:48
MERCI BruNews,ça marche enfin.
Et effectivement,j'ai encore beaucoup de choses
à apprendre,mais c'est cela qui me motive.

Bonne Prog.
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
14 janv. 2013 à 18:08
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...
0
cs_parki Messages postés 75 Date d'inscription mardi 29 juillet 2008 Statut Membre Dernière intervention 25 mars 2019
14 janv. 2013 à 22:32
à 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

???
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 janv. 2013 à 11:20
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...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 janv. 2013 à 13:00
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...
0
cs_parki Messages postés 75 Date d'inscription mardi 29 juillet 2008 Statut Membre Dernière intervention 25 mars 2019
16 janv. 2013 à 10:00
Merci pour l'info.
0
Rejoignez-nous