[ Assembler ] — начинающим: задаем вопросы

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by !_filin_!, 25 May 2007.

  1. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    Юго,
    Чётко. Внатуре чётко.
    [​IMG]

    Киев,
    Так же, как и исходники Windows в пачку сигарет.

    *.asm - формат файла, содержащий исходный текст программы, написанной на языке ассемблера.
    Шеллкод - специфически написанный код, обладающий чудным свойством - базонезависимостью.
    Превращать тут надо не *.asm, а сам код. А ответит конкретно на такой вопрос сможет только тот человек, который может научить программировать на С++ за пару минут.

    Шеллкод - http://forum.antichat.ru/showpost.php?p=2887126&postcount=1183
    Генерация шеллкода в виде бинарного потока в файл http://forum.antichat.ru/showpost.php?p=2891318&postcount=1192
    P.S. Masm32
     
    1 person likes this.
  2. BlackMiay

    BlackMiay Member

    Joined:
    25 Sep 2011
    Messages:
    17
    Likes Received:
    12
    Reputations:
    3
    ASM и DLL Помогите!

    Объясните наконец, уже 6 часов бьюсь и не могу понять.
    Вот статья , про динамические библиатеки.
    Там есть процедура именно в dll
    PHP:
    TestHello proc       
    invoke MessageBox
    ,NULL,addr HelloMsg,addr AppName,MB_OK      ret      
    TestHello endp
    Так вот как мне туда передать целочисленный массив и выполнить над ним какие-небудь действия и вернуть обратно. И ещё я использую invoke LoadLibrary в основном приложении. Очень нуждаюсь в вашей помощи.
    Кстати вот ссылка на пример .
     
  3. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Почитай доки по синтаксису MASM. Там всё написано, и не придется 6 часов сидеть.

    Передаются аргументы так:
    PHP:
    TestHello proc arg1 :DWORDarg2 :DWORDarg3 :DWORD

    TestHello endp  
    где arg1, arg2, arg3 - твои аргументы. Так как MASM32 - малотипизированный язык, в них можно совать и числа, и указатель на начало твоего целочисленного массива, и указатель на строку.

    Возвращать аргумент из функции можешь как угодно - например, в любом регистре (тогда ты сможешь вернуть 4 байта (DWORD)), либо вообще записывать возвращаемые данные по некоторому адресу, который передан функции. Прочитай про конвенции вызовов, и увидишь, каким условиям должны удовлетворять функции stdcall (такое соглашение используют практически все функции WinAPI). В stdcall значение возвращается через регистр eax.
     
  4. BlackMiay

    BlackMiay Member

    Joined:
    25 Sep 2011
    Messages:
    17
    Likes Received:
    12
    Reputations:
    3
    Спасибо, немного продвинулся, но всё же, есть вопросы.
    Я отправляю в функцию размер масива и его самого
    PHP:
    ...
    push len                           
    push m                          
    call EAX
    ...
    Но ведь stdcall функция может возврашать только eax... Ступор :(

    Как мне передать мои данные это в функцию, изменить их, а затем вернуть обратно?

    PHP:
    Sum proc ;buf:DWORD
         push EBP
         mov EBP
    ESP
         mov EСX
    , [EBP+8] ; здесь лежит мой размер (len)
         
    mov ebx, [EBP+12] ; здесь первый элемент массива (m)
                  
    mov EAX,Это походу что вернёт моя функция...
         
    pop EBP
         ret 
     Sum endp
    Пожалуйсто помогите разобраться, я из гугла уже n времени не вылезаю...

    Ещё вопрос могу ли я из динамической функции работать с регистром из своей программы, к примеру
    PHP:
    ...
    mov esiOFFSET m
    ...
    Будет ли доступна для функции из библиотеки?
     
    #1224 BlackMiay, 6 Mar 2012
    Last edited: 6 Mar 2012
  5. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Ты можешь менять тот же самый массив, который передал в функцию. Ты можешь передать таким же образом второй массив, предварительно создав его в вызывающей функцию программе, а из дллки в него писать данные. Ты даже можешь создать в дллке массив (динамически выделить память), в него записать нужные данные, а адрес массива вернуть через eax, хотя это не очень хороший тон. Посмотри на любую winapi-функцию, возвращающую, скажем, строку, например, GetUserName. Они все принимают указатель на массив, который ты выделяешь в своей программе, и пишут в него данные.

    Динамическая библиотека, подгруженная в адресное пространство твоего процесса - это часть процесса, она может делать все, что угодно, в том числе, менять регистры вызывающей программы. Но если ты хочешь сделать так, чтобы твою дллку могли использовать все программы, создавай в ней функции с использованием какой-либо конвенции вызовов. Если это stdcall, то значение возвращай в eax, принимай значения через стек, и сохраняй значения регистров edi, esi и ebx (push edi, push esi, push ebx в начале кода функции и pop ebx, pop esi, pop edi в конце. Можно еще директиву uses масма32 использовать).
     
  6. BlackMiay

    BlackMiay Member

    Joined:
    25 Sep 2011
    Messages:
    17
    Likes Received:
    12
    Reputations:
    3

    Да я понимаю, что это возможно, от части задачу я решил записав в стек размер массива и записав всё значение массива в регистр, перед вызовом функции
    PHP:
    ...
    push len
    mov esi
    OFFSET m
    call EAX
    ...
    Т.е хотелось бы увидеть пример, как сделать так
    1. Записываем в стек адрес массива
    2. Получаем в dll этот адрес и начинаем, допустим увеличивать значения массива на 1, при этом я так понимаю, мы должны взять к примеру этот же регистр, загнав его в стек?!
    3. Как через еах вернуть адрес уже изменённого масива?!
    4. Получается что мою написаную dll не могут исползувать сразу несолько приложений, так для них всех регистр esi будет обшим? (Это наверное для вас самый нубский вопрос...)

    Я не могу найти ни одного примера в интернете с аргументами в процедуре dll и вообще как потом вернуть значение в EAX???
    И как потом написать код допустим в Delphi для вызова данной функции, там же я не определяю в какой регистр я пишу?

    Пожалуйсто приведите пример. Очень прошу.
    Кстати вот моей функции в dll
    PHP:
    ...
     
    Sum proc 
         push EBP
         mov EBP
    ESP
         mov ecx
    , [EBP+8] ; Считываем из стека размер массива.
        
    mov edx,ecx
        dec ecx
        for_i
    :
            
    push ecx
            neg ecx
            add ecx
    edx
        for_j
    :
            
    mov eax, [esi][ecx*4]
            
    mov ebx, [esi][ecx*4-4]
            
    cmp ebxeax
            jg skip
            mov 
    [esi][ecx*4], ebx
            mov 
    [esi][ecx*4-4], eax
            skip
    :
            
    loop for_j    
        pop ecx
        loop for_i
         pop EBP
         ret 4
     Sum endp
    ...
     
    #1226 BlackMiay, 6 Mar 2012
    Last edited: 6 Mar 2012
  7. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Сейчас глупые вопросы пошли. Советую почитать, что такое вообще регистры, стек, куча и т.п. базовые вещи. Если мы передали в функцию (неважно, где эта функция, в dll, не в dll) АДРЕС массива и работаем с этим адресом изнутри функции, то мы работаем с тем самым массивом, который лежит где-то в памяти программы, которая вызвала функцию. Массив при этом НЕ дублируется, т.к. мы передали указатель на его начало. Адрес.

    Если мы не хотим, чтобы наш изначальный массив менялся, то делаем, например, так. Передаем два адреса в функцию: первый адрес - адрес массива с исходными данными, второй адрес - адрес массива с неопределенными данными, в который функция будет писать результат. Функция в цикле берет каждый элемент первого массива, делает с ним какие-то операции, а результат записывает во второй массив. На выходе у нас получается неизмененный исходный массив и заполненный нужными нам значениями второй.

    Пример не буду приводить, тут и так все очевидно.

    Соответственно, этот вопрос отпадает.

    Смогут, у каждого процесса свое адресное пространство, свои значения регистров, свой стек и своя куча. Ну только если ты принудительно не сделаешь некоторую секцию исполняемого файла shared.
     
  8. BlackMiay

    BlackMiay Member

    Joined:
    25 Sep 2011
    Messages:
    17
    Likes Received:
    12
    Reputations:
    3
    И Снова Ассемблер+процедуры...

    И так вот кусок кода, приложения.
    PHP:
    ...

    incMass :DWORD, :DWORD

    mas DD 100 DUP
    (?)
    ln  DD 0
    ...
    Здесь код заполнения массива
    ...
    INVOKE incMass,mas,ln вызов функции из dll 
    ...
    Собсвенно вот кусок dll кода, в кором я не пойму некорое вещи
    1. Как передать этот массив в код, переписать его эл-ты на 1, и вернуть обратно???

    PHP:
    ...
    incMass PROC m:DWORDl:DWORD
    mov ecx
    ,l
    lea esi
    ,m
    mov ebx
    ,1
    start
    :
    mov [esi],ebx
    add esi
    ,4
    loop start
    ret
    incMass endp
    ...
    Эта процедура из dll у меня не работатет, и никак не могу найти информацию с подобным примером. Поправте пожалуйсто, если не трудно эту процедуру...

    И ещё как я понял если использовать CALL то аргументы передаються только через СТЕК???
    Почему в длл кампилятор рунаеться на OFFSET?
     
    #1228 BlackMiay, 9 Mar 2012
    Last edited: 9 Mar 2012
  9. DooD

    DooD Elder - Старейшина

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    450
    Reputations:
    288
    что именно не работает?дебаггером пройдись.через стек если передавать то вызов колл-ом.если укажешь прототип то можно и через инвок вызывать.
     
  10. LASS0

    LASS0 Member

    Joined:
    3 Jan 2009
    Messages:
    0
    Likes Received:
    17
    Reputations:
    1
    Помогите пожалуйста дописать программу, сейчас она только считывает и выводит каждый элемент массива.
    Нужно обнулить все элементы массива, которые по модулю меньше 10


    PHP:
    include 'win32ax.inc'
     
    .data
     
    array db 5,34,9,98,-массив
    array_len db 
    $-array
     
    Caption db 'Результат.',0
     
    buffer  rb 20
     
     
    .code
     
     
    start
    :
     
    xor 
    eax,eax
    xor ecxecx
     
    mov cl
    , [array_len]
     
    mov edibuffer
    mov esi
    , array
     
    m:
     
     xor 
    eax,eax
     mov al
    ,[esi] ; помещаем элемент массива в регистр al
     
    ;
     ; 
    здесь надо заменить al нулемесли он по модулю меньше 10
     
    ;
     
    call IntToStr Выводим элемент массива
     
     inc esi
     inc edi
     
    loop m
     
    mov 
    [edi], byte 0
     
     
     
     
     
     
    invoke MessageBox
    ,0,buffer,Caption,MB_OK
    invoke ExitProcess
    ,0
     
    IntToStr
    :
     ;
    eax numberebx base(основание системы счисления=10), edi buffer(буфер для хранения строки ;результата)
            
    push eax ecx ebx edx
            
    xor     ecx,ecx
            mov     ebx
    10
     
          
    .new:
            xor     
    edx,edx
            div     ebx
            push    edx
            inc     ecx
            test    eax
    ,eax
            jnz     
    .new
          .
    loop:
            
    pop     eax
            add     al
    ,30h
            mov    
    [edi], al
            inc    edi
            loop    
    .loop
            mov    al
    byte ' '
            
    mov    [edi],al
            pop edx ebx ecx eax
            ret
    .end start
     
  11. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    811
    Reputations:
    231
    Code:
     test al,al
     jns skip
     neg al
    skip:
    
     cmp al,10
     ja skip2
     mov al,0
    skip2:
    
     
    _________________________
    1 person likes this.
  12. DeepBlue7

    DeepBlue7 Elder - Старейшина

    Joined:
    2 Jan 2009
    Messages:
    359
    Likes Received:
    50
    Reputations:
    12
    Возник вот такой вопросег о так называемых "регистрах процессора".

    Суть вопроса - регистры одни, или их несколько ? Т.е. при запуске двух приложений, соответственно есть два "блока" регистров. Допустим, в одном преложении eax = 5, а во втором - 10. Вообщем, обьясните, "сколько" их.

    Надеюсь, смысл ясен :)
    Заранее благодарю.
     
  13. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Регистры в процессоре одни. Один eax, один esi и т.д. На каждое ядро по одному. Операционная система занимается тем, что переключает контексты процессов и потоков, сохраняя состояние регистров процесса, который она приостанавливает, и восстанавливая регистры для того, который она запускает на выполнение.
     
  14. DeepBlue7

    DeepBlue7 Elder - Старейшина

    Joined:
    2 Jan 2009
    Messages:
    359
    Likes Received:
    50
    Reputations:
    12
    Большое спасибо, прояснил. Подозревал, что это так, просто это стоило бы писать в обучалках ).

    Кстати, получается, отладчики в некотором смысле берут на себя то, что должна делать ось ?
     
    #1234 DeepBlue7, 12 Mar 2012
    Last edited: 12 Mar 2012
  15. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Отладчики могут контролировать состояние памяти и регистров какого-либо процесса, переключением контекстов они не занимаются.
     
  16. altblitz

    altblitz Elder - Старейшина

    Joined:
    5 Jun 2009
    Messages:
    3,694
    Likes Received:
    3,148
    Reputations:
    236
    исключено.
    делаешь "Step by step" кода в отладчике - и видишь, как меняется содержание регистров.

    отладчики - не хирурги, а судебно-медицинские эксперты.
    фиксируют лишь изменения в памяти и регистрах, которые ты сам внёс, своим кодом.
     
    1 person likes this.
  17. SEKTOR3A

    SEKTOR3A New Member

    Joined:
    2 May 2009
    Messages:
    36
    Likes Received:
    1
    Reputations:
    0
    вопрос как после создание файла
    invoke CreateFile,addr file,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0

    записать с поле EDIT в файл file

    в моем случае поле вода пароля выглядит так

    dialogitem 'EDIT','',ID_PASS,55,11,110,12,WS_CHILD+WS_VISIBLE+ES_CENTER+WS_BORDER+ES_PASSWORD

    хоть не большой пример скиньте должен ли я еще использовать функцию записи
    invoke WriteFile
     
  18. DooD

    DooD Elder - Старейшина

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    450
    Reputations:
    288
    юзаешь GetWindowText в связке с WriteFile.
     
  19. SEKTOR3A

    SEKTOR3A New Member

    Joined:
    2 May 2009
    Messages:
    36
    Likes Received:
    1
    Reputations:
    0
    создается файл но туда не чего не записывается

    вот пример
    PHP:
    IF ax == BN_CLICKED
                        invoke    MessageBox
    ,hWnd,addr TextButton1,0,MB_ICONINFORMATION
                        invoke CreateFile
    ,addr fname,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
                        invoke GetWindowText
    Edit1ID,ADDR buf,512
                        invoke WriteFile
    ,fname,TextEdit1,Edit1ID,addr buf,512
     
  20. DooD

    DooD Elder - Старейшина

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    450
    Reputations:
    288
    смори
    Code:
    invoke GetWindowText,hwndEdit,addr buffer,512
    Code:
    invoke GetWindowTextLength,hwndEdit
    получили длину текста.
    получили текст,ок.
    Code:
    invoke WriteFile,hFile,addr buffer,eax,addr htemp,0
    записали.