Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.02.2013, 20:15   #1
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию scanf

Пытаюсь освоить основы Асма.
Написал вот такой код. в FASMe
Код:
format PE console
entry start

include 'win32a.inc'



section '.text' code executable
start:

        push param
        push [val]
        call [scanf]

        push hello
        call [printf]
        pop ecx

        push 0
        invoke  Sleep,-1
        call [ExitProcess]

section '.rdata' data readable
        hello db 'Hello world!', 10, 0
        param db '%d'
  val dd 0
  c dd 0

section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess',\
                         Sleep, 'Sleep'

        import msvcrt, printf, 'printf', \
                       scanf, 'scanf'
Программа должна считать некоторые данные но ввод не работает лишь только вывод привет мир. Скажите пожалуйста почему не работает и как организовать чтение scanf()?
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 09.02.2013, 20:37   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

В scanf передается указатель. Так что нужно push val
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.02.2013, 21:00   #3
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

а разве [val] не есть указатель, а не значение? и у меня такое подозрение что она может быть хочет гораздо больше параметров скушать? для всяких там varargs.

о! вот так вот заработало...

Код:
 
section '.text' code executable
start:


      invoke scanf, param, val

        push hello
        call [printf]
        pop ecx

        push 0
        invoke  Sleep,-1
        call [ExitProcess]
только теперь "привет мира" нет ( вылет похоже.

а так есть и привет мир
Код:
section '.text' code executable
start:


	invoke scanf, param, val

	invoke printf, hello

	pop ecx

	push 0
	invoke	Sleep,-1
	call [ExitProcess]
Но он есть только буквы, а на цифрах вылетает это при том что как бы для сканфа %d задано.
Странно как-то, в чем может быть дело?
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки

Последний раз редактировалось intmain; 09.02.2013 в 21:29.
intmain вне форума Ответить с цитированием
Старый 09.02.2013, 21:39   #4
vadimych
Форумчанин
 
Регистрация: 16.01.2011
Сообщений: 325
По умолчанию

Функции из msvcrt не чистят за собой стек. Надо делать это руками.
Код:
format PE console
entry start

include 'include\win32a.inc'



section '.text' code executable
start:
        push val
        push param
        call [scanf]
        add esp,8
        
        push hello
        call [printf]
        add esp,8

        push [val]
        push param
        call [printf]
        add esp,8

        call [getch]

        push 0
        call [ExitProcess]

section '.data' data readable writeable
        hello db 'Hello world!', 10, 13,0
        param db '%d',0
  val dd 0

section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess',\
                         Sleep, 'Sleep'

        import msvcrt, printf, 'printf', \
                       scanf, 'scanf',\
                       getch, '_getch'
vadimych вне форума Ответить с цитированием
Старый 09.02.2013, 21:55   #5
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Получилось кое-что, но мне не понятно одно, - откуда сканф выделяет себе память для переменной куда будут заноситься данные (val) если я выделел всего 3 байта ( val db '12', 0) Откуда береться остальная память? и почему оно ни вопиет если водиться строчка более 2-3 символов?

Код:
format PE console
entry start

include 'win32a.inc'



section '.text' code executable
start:
        invoke scanf, param_string, val
        invoke printf, val
        invoke printf, hello


        invoke  Sleep,-1
        call [ExitProcess]

; ïåðåìåííûå äîñòóïíûå äëÿ çàïèñè ÷òåíèÿ
section '.data' data readable writeable
        ;read-write
        val db '12', 0
        c dd 0

;êîíñòàíòû
section '.rdata' data readable
        ;read only
        hello db 'Hello world!', 10, 0
        param_string db '%s', 0


section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess',\
                         Sleep, 'Sleep'

        import msvcrt, printf, 'printf', \
                       scanf, 'scanf'
Спасибо vadimych.
Цитата:
Функции из msvcrt не чистят за собой стек
точно. это наверное связано с соглашения об вызовах ф-й да?
это cdecl ф-й принцип не чистить за собой?

Но я что-то смутно представляю как работает стек. я знаю его алгоритмическое представление и практическое назначение но вот приминительно к низкоуровнему програмирование не очень.

add esp, 8 это мы куда по стеку перемещаемся? и почему именно 8? )
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 09.02.2013, 23:31   #6
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

Цитата:
Откуда береться остальная память? и почему оно ни вопиет если водиться строчка более 2-3 символов?
Нигде не берёт. Сначала "c" затрёт, которая после "val", потом, возможно, ещё что-то, но ничем хорошим не закончится.
Цитата:
это cdecl ф-й принцип не чистить за собой?
Да. Иначе было бы проблематично чистить неизвестное заранее неизвестное количество аргументов.
Цитата:
add esp, 8 это мы куда по стеку перемещаемся? и почему именно 8?
8 - размер параметров, которые затолкали в стек перед вызовом. После printf hello, наверное, опечатка, потому что там 4. Стек растёт от верхних адресов к нижним, так что add - это в сторону уменьшения размера стека.

Замени invoke на cinvoke, а то память утекает. И у ExitProcess параметр есть. Кстати, возвращаться можно просто ret'ом, если со стеком всё хорошо.
Somebody вне форума Ответить с цитированием
Старый 10.02.2013, 06:17   #7
vadimych
Форумчанин
 
Регистрация: 16.01.2011
Сообщений: 325
По умолчанию

Цитата:
После printf hello, наверное, опечатка
Совершенно верно. Забыл поправить.
vadimych вне форума Ответить с цитированием
Старый 10.02.2013, 09:31   #8
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Цитата:
Нигде не берёт. Сначала "c" затрёт
ясно, спасибо.

Цитата:
Стек растёт от верхних адресов к нижним, так что add - это в сторону уменьшения размера стека.
примерно понятно нужно больше попрактиковаться с ним. что бы нарисовать картинку в голове как он работает.
а ebp он указывает смещения от esp? т.е адресует внутри стека так? получается когда мы ложим в стек новое значение push x - меняя esp, то и ebp меняется?

у меня новая проблема. программа не хочет работать с процедурой sub1
Код:
format PE console
entry start

include 'win32ax.inc'
;include 'PROC32.INC'

section '.text' code executable
start:

        stdcall sub1
        ;add esp, 4
        cinvoke scanf, param_string, val
        cinvoke printf, val
        cinvoke printf, hello


        cinvoke getch
        cinvoke ExitProcess, 0

proc sub1
     invoke printf, sub1_string
     ret
endp


; ïåðåìåííûå äîñòóïíûå äëÿ çàïèñè ÷òåíèÿ
section '.data' data readable writeable
        ;read-write
        val db '12', 0
        c dd 0

;êîíñòàíòû
section '.rdata' data readable
        ;read only
        hello db 'Hello world!', 10, 0
        sub1_string db 'this is a sub',10, 0
        param_string db '%s', 0


section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess',\
                         Sleep, 'Sleep'

        import msvcrt, printf, 'printf', \
                       scanf, 'scanf' , \
                       getch, '_getch'
вылетает. что может быть?

////
извиняюсь поправил
Код:
proc sub1
     cinvoke printf, sub1_string
     ret
endp
вроде работает

тогда еще вопрос как считать int и float? потому как scanf читает строки по идее нужно както их преобразовывать в числа?
наверно, можно и самим сканфом считать через "%f" "%d" ?
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки

Последний раз редактировалось intmain; 10.02.2013 в 09:37.
intmain вне форума Ответить с цитированием
Старый 10.02.2013, 11:30   #9
intmain
Играюсь с Python
Форумчанин
 
Аватар для intmain
 
Регистрация: 12.12.2012
Сообщений: 340
По умолчанию

Почему после ввода float на экран выводиться не то число что ввел ?
Код:
format PE console
entry start

include 'win32ax.inc'
;include 'PROC32.INC'

section '.text' code executable
start:

        stdcall sub1

        ;mov eax, [float_index]
        ;inc eax
        ;mov [float_index], eax
        add [float_index], 1
        cinvoke printf, param_promt, [float_index]
        cinvoke scanf, param_float, float1
        cinvoke printf, param_float, float1


        ;cinvoke scanf, param_string, val
        ;cinvoke printf, val
        ;cinvoke printf, hello
        cinvoke getch
        cinvoke ExitProcess, 0

proc sub1
     cinvoke printf, sub1_string
     ret
endp


; ïåðåìåííûå äîñòóïíûå äëÿ çàïèñè ÷òåíèÿ
section '.data' data readable writeable
        ;read-write
        val db '12', 0
        c dw 0
        float1 dd 0
        float2 dd 0
        float3 dd 0
        float_index dd 0;

;êîíñòàíòû
section '.rdata' data readable
        ;read only
        hello db 'Hello world!', 10, 0
        sub1_string db 'this is asm proc',10, 0
        param_string db '%s', 0
        param_float db '%f',0
        param_promt db 'enter float %d: ', 0


section '.idata' data readable import
        library kernel32, 'kernel32.dll', \
                msvcrt,   'msvcrt.dll'
        import kernel32, ExitProcess, 'ExitProcess',\
                         Sleep, 'Sleep'

        import msvcrt, printf, 'printf', \
                       scanf, 'scanf' , \
                       getch, '_getch'
Что ел то - в долг, что жил то - зря.
Для избранных. ))
Секретные разработки
intmain вне форума Ответить с цитированием
Старый 10.02.2013, 11:43   #10
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

ebp - более-менее обычный регистр, от push/pop/call/ret не меняется. (Меняется от enter/leave, но это сейчас достаточно редкие инструкции.) Обычно фунции выглядят как-то так:
Код:
push	ebp
mov	ebp, esp
sub	esp, localsSize
...
mov	esp, ebp
pop	ebp
ret
[ebp - x] - локальные переменные, [ebp] - предыдущее значение ebp, [ebp + 4] - адрес возврата, [ebp + x] - параметры функции.
А printf не может выводить float, %f - это double.
Somebody вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
scanf и матрица Berlioz Общие вопросы C/C++ 4 24.09.2012 15:12
Считывая нулей scanf nukede Общие вопросы C/C++ 3 05.04.2012 21:44
Проблема с функцией scanf() ichigo9911 Общие вопросы C/C++ 1 26.02.2012 21:12
доступ к переменным из scanf zl@dey Общие вопросы C/C++ 3 21.12.2011 13:49
аналог scanf() turtles Общие вопросы по Java, Java SE, Kotlin 1 09.04.2011 10:33