Vedo di farti un esempio per farti capire.
modulo c++
#include "stdafx.h"
#include "iostream"
using std::cin;
using std::cout;
using std::endl;
extern "C" int __stdcall LenStringa(char*);
extern "C" int __stdcall pleftstringa(char *,char *,int);
int _tmain(int argc, _TCHAR* argv[])
{
char pippo[71],pluto[68];
int ncar,indy,kindy,err,opz;
ncar=0; err=0; kindy=0; opz=0;
for (indy=0;indy < 71;indy++) { pippo[indy]=' '; }
for (indy=0;indy < 68;indy++) { pluto[indy]=' '; }
cout << "inserisci stringa una stringa max 70 caratteri : ";
cin.getline(pippo,71);
cout << "quanti caratteri vuoi prendere ? ";
cin >> ncar;
err = pleftstringa(pippo,pluto,ncar);
cout << "hai preso i seguenti caratteri : " << pluto << "\n";
return 0;
}
nella parte assembler
.486
.model flat,stdcall
option casemap :none
.code
pleftstringa PROC Arg1:DWORD,Arg2:DWORD,Arg3:DWORD
; adesso se aggiungo
call geteip
mov ecx,Arg3
mov edi,Arg2
mov esi,Arg1
cmp ecx,0
jne uno
mov eax,2
jmp short fine
uno:
cmp byte ptr [esi],0
jne due
mov eax,1
jmp short fine
due:
xor eax,eax
rep movsb
mov dword ptr [edi],0
fine:
ret
getip:
pop eax
push eax
mov ebx,6 ; questo perchè questa routine in memoria, se ho fatto bene i calcoli, occupa 6 byte
ret
pleftstringa endp
end
; in teoria succederebbe che prende l'indirizzo del registro eip e lo mette in eax
; e poi continuerebbe con il flusso normale della routine assembler.
; ma in pratica mi esce dalla routine senza aver fatto niente!
;prende solo l'indirizzo eip
; cioè per il compilatore ogni volta che incontra una ret significa che è finita la routine assembler tornando al c++.
la soluzione potrebbe consistere in una routine a se stante in un file a parte.
ma cio' porterebbe ad un problema di memoria.
infatti il modello flat a differenza dei modelli tiny,small e compact lascia molto spazio tra una routine e un altra a volte gli cambia anche il segmento,anche se a volte non ce ne accorgiamo dipende dalle dimensioni del programma.
per questo motivo non va bene questa tecnica.