Strona 1 z 1

String to int, C&ASM

: 06 kwietnia 2008, 19:24
autor: November
Chcę zamienić stringa na inta, wpisuje dane w C, daje je do funkcji w ASM i wynik daje do C, gdzie go wyświetlam.

Kod: Zaznacz cały

#include <stdio.h>

extern char suma (char a);


int main(void)
	{
	char g[100] = { "Programowanie" };
	printf("podaj jakas wart: ");
	scanf("%s", g);
	printf("%s\n", g);

	printf("%d\n", 	suma (*g));
	return 0;
}
Mam taki kod w C, teraz go sobie zrobiłem takie coś

Kod: Zaznacz cały

gcc -S call.c
, by zobaczyć jak on to tam wysyła do rejestrów.

Kod: Zaznacz cały

	.file	"call.c"
	.section	.rodata
.LC1:
	.string	"podaj jakas wart: "
.LC2:
	.string	"%s"
.LC3:
	.string	"%d\n"
.LC0:
	.string	"Programowanie"
	.zero	86
	.text
.globl main
	.type	main, @function
main:
.LFB2:
	pushq	%rbp
.LCFI0:
	movq	%rsp, %rbp
.LCFI1:
	subq	$112, %rsp
.LCFI2:
	movq	.LC0(%rip), %rax
	movq	%rax, -112(%rbp)
	movl	.LC0+8(%rip), %eax
	movl	%eax, -104(%rbp)
	movzwl	.LC0+12(%rip), %eax
	movw	%ax, -100(%rbp)
	leaq	-98(%rbp), %rdi
	movl	$86, %edx
	movl	$0, %esi
	call	memset
	movl	$.LC1, %edi
	movl	$0, %eax
	call	printf
	leaq	-112(%rbp), %rsi
	movl	$.LC2, %edi
	movl	$0, %eax
	call	scanf
	leaq	-112(%rbp), %rdi
	call	puts
	movzbl	-112(%rbp), %eax
	movsbl	%al,%edi
	call	suma
	movsbl	%al,%esi
	movl	$.LC3, %edi
	movl	$0, %eax
	call	printf
	movl	$0, %eax
	leave
	ret
.LFE2:
	.size	main, .-main
	.section	.eh_frame,"a",@progbits
.Lframe1:
	.long	.LECIE1-.LSCIE1
.LSCIE1:
	.long	0x0
	.byte	0x1
	.string	"zR"
	.uleb128 0x1
	.sleb128 -8
	.byte	0x10
	.uleb128 0x1
	.byte	0x3
	.byte	0xc
	.uleb128 0x7
	.uleb128 0x8
	.byte	0x90
	.uleb128 0x1
	.align 8
.LECIE1:
.LSFDE1:
	.long	.LEFDE1-.LASFDE1
.LASFDE1:
	.long	.LASFDE1-.Lframe1
	.long	.LFB2
	.long	.LFE2-.LFB2
	.uleb128 0x0
	.byte	0x4
	.long	.LCFI0-.LFB2
	.byte	0xe
	.uleb128 0x10
	.byte	0x86
	.uleb128 0x2
	.byte	0x4
	.long	.LCFI1-.LCFI0
	.byte	0xd
	.uleb128 0x6
	.align 8
.LEFDE1:
	.ident	"GCC: (GNU) 4.2.3 (Debian 4.2.3-3)"
	.section	.note.GNU-stack,"",@progbits
Widać tam wyraźnie, że C wysyła mi jedynie pierwszą literę ze stringa :/
movzbl -112(%rbp), %eax
movsbl %al,%edi

Mam taka funkcję w asm dla gcc

Kod: Zaznacz cały

.globl suma
	.type	suma, @function
suma:
	#ramka
	pushq	%rbp
	movq	%rsp, %rbp
	#koniec ramki
	
	movl	%edi, -4(%rbp)
	movl	-4(%rbp), %eax
	
	#wyjscie
	leave
	ret
	.size	fun, .-fun
Bądź taką dla NASM'a

Kod: Zaznacz cały

	section .text ;use64

	global	suma

	suma:
;############## Rozpoczęcie ramki
		push	rbp
		mov	rbp, rsp
;############## Wyświetlenie liczby ramki

		mov	[rbp-4], edi
		mov	eax, [rbp-4]

;############## Zakończenie ramki
		leave
		ret
Efekt działa takiego programu to:

Kod: Zaznacz cały

 ./suma 
podaj jakas wart: rty
rty
114

$ ./suma 
podaj jakas wart: r
r
114
Czyli widać dokładnie to, że wysyła tylko jedną literę... A może wysyła wszystkie, tylko gdzie one wtedy są? :shock:

: 07 kwietnia 2008, 00:08
autor: Theq
Widać tam wyraźnie, że C wysyła mi jedynie pierwszą literę ze stringa :/
Ale o co chodzi? Masz przeciez suma(char a) a to jest jeden znak, wiec co ma wysylac ;)

: 07 kwietnia 2008, 19:21
autor: Stawi
Po pierwsze: extern char suma (char *a);

Po drugie widac wyraznie ze nic nie idzie na petli wiec jak ma zliczac nastepne znaki? Przesuwaj wskaznik (zwiekszaj rejestr) az wartosc na ktora pokazuje bedzie rowna zero (czyli koniec stringa).

: 09 kwietnia 2008, 22:57
autor: painspr
deklaracje funkcji zmień jak Stawi napisał czyli :

Kod: Zaznacz cały

extern suma(char *g);
i wywołuj suma(g), jak dasz operator * to pobierze wartość z adresu wskazywanego przez wskaźnik, a nazwa tablicy jest właśnie wskaźnikiem

i wydaje mi się, że parametry chyba zaczynają się od [ebp-8] (u Ciebie [rbp-8]) bo jeszcze ślad funkcji jest na stosie albo jeszcze lepiej [rbp-12] bo rbp jest chyba 8 bajtowy, nie wiem jak jest ze śladem na 64bitowych, czy jest też 64bitowy