|
String to int, C&ASM
November - 06-04-2008 19:24
Chcę zamienić stringa na inta, wpisuje dane w C, daje je do funkcji w ASM i wynik daje do C, gdzie go wyświetlam.
#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ś gcc -S call.c
, by zobaczyć jak on to tam wysyła do rejestrów. .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 .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 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: ./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:
Theq - 07-04-2008 00:08
Ale o co chodzi? Masz przeciez suma(char a) a to jest jeden znak, wiec co ma wysylac ;)
Stawi - 07-04-2008 19:21
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).
painspr - 09-04-2008 22:57
deklaracje funkcji zmień jak Stawi napisał czyli : 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
zanotowane.pldoc.pisz.plpdf.pisz.plminister.pev.pl
|