J'ai essayé certains appels ASM à partir de C et vice versa. Cela a fonctionné parfaitement au moins pour l'instant mais j'ai des questions. Voici mon code:A propos de l'appel de la fonction C à partir de l'assemblage et vice versa
test.S suivi:
.text
.global _start
.global _main
.type _main, @function
.global writeMe
.type writeMe, @function
_start:
#; Write hello world for 5 times.
#; Jump exit and call C function after that.
#; C function calls writeMe assembly function
#; Exit with syscall
xorl %ecx, %ecx #; ecx = 0
call _get_eip #; get eip without labels. Just for research.
pushl %eax #; push to stack
incl %ecx #; ++ecx
pushl %ecx #; push to stack
movl $len,%edx #; tell length of string
movl $msg,%ecx #; tell string position
movl $1,%ebx #; fd = stdout
movl $4,%eax #; syscall = write
int $0x80 #; perform call
popl %ecx #; pop counter
movl %ecx, %eax #; eax = ecx
cmpl $0x5, %eax #; compare 0x5 and eax
je _exit #; eax == 0x5, jump exit
_jmp:
popl %eax #; pop instruction pointer
jmpl %eax #; jmp
_exit:
call _main #; call C function
movl $0,%ebx #; EXIT_SUCCESS
movl $1,%eax #; syscall = exit
int $0x80 #; perform call
ret
_get_eip: #; function for getting eip
popl %eax #; pop eip
pushl %eax #; push again to return
ret #; return location
writeMe: #; function for writing, called from C
popl (__eip) #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call
pushl (__eip) #; push return location
ret #; return location
writeMe2: #; function for writing, called from C
popl %ecx #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call
subl $0x0C, %esp #; restore stack
ret
.data
__eip: .long
msg:
.ascii "Hello, world!\n\0"
len = . - msg
MAIN.C suivi:
extern void writeMe(const char *msg, int len);
int _strlen(const char *msg) {
int _len = 0;
while (*msg++ != 0x0)
_len++;
return _len;
}
void _main() {
const char * szmsg = "Hello, world!\n";
writeMe(szmsg, _strlen(szmsg));
}
Ma sortie est comme ce que je pensais.
Bonjour, monde!
Bonjour, monde!
Bonjour, monde!
Bonjour, monde!
Bonjour, monde!
Bonjour, monde!
Mes questions suivies:
1)
.type writeMe, @function
Qu'est-ce que ce code signifie? Information pour "GCC"? Qu'est ce que ça fait? Est-ce que je dois faire ça?
2)
Dois-je écrire cette op délation. si la fonction a été déclarée dans le fichier C?
.type _main, @function
_main est déclaré dans le fichier C, dois-je écrire?
3)
popl (__eip) #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
........
pushl (__eip) #; push return location
Je l'ai utilisé ce code dans writeMe, est-il sûr? En d'autres termes, puis-je afficher des arguments, ou GCC va-t-il l'afficher automatiquement?
popl %ecx #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
....
subl $0x0C, %esp #; restore stack
J'ai utilisé ce code en seconde fonction. Je vous demande, lequel est sûr et correct?
4) Ai-je besoin de restaurer les registres après avoir appelé la fonction d'assemblage de C? (J'ai entendu que je dois restaurer l'EDI mais qu'en est-il des autres?)
Merci pour toutes vos réponses.
Il existe quelques liens utiles sur http://stackoverflow.com/tags/x86/info. esp: comment utiliser un débogueur sur votre code asm, et des liens vers des guides/tutoriels. –