Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Assembler

Автор: vjick
Дата сообщения: 05.03.2013 20:20
Установил Microsoft Visual Studio 2010 Ultimate. Создаю новый проект Win32 - console application. В Source добавляю .asm файл... на этой стадии судя по руководствам должен спросить чем компилировать.. однако ничего не появляется и при попытке компиляции выбивает ошибку. Подскажите, как быть?
Автор: bomzzz
Дата сообщения: 05.03.2013 20:21
masm32 поставить вместо этого уродца студийного
http://www.masm32.com/
Автор: vjick
Дата сообщения: 05.03.2013 20:23
а других вариантов решения нету?..
Автор: bomzzz
Дата сообщения: 05.03.2013 20:39
ну есть наверняка, только для асма в студии нет инклудов, если ты там чтото глобальное затеял на ассемблере ваять, то без инклудов у тебя будет в несколько раз больше работы. придется значение самых простых переменных искать в мсдне. основные инклуды с переменными в масме весят два мегабайта и они далеко не полные
Автор: vjick
Дата сообщения: 05.03.2013 20:43
человеку помочь задачу решить. ничего глобального. раньше точно помнюю что в VS2010 нормально все получалось... толи забыо что-то, то ли перепутал

Добавлено:
bomzzz
а как masm этот ставить? скачал, запускаю. раз 5 ОК нажимаю и в итоге никуда программа не устанавливается. епсель мопсель
Автор: ne_viens
Дата сообщения: 06.03.2013 09:37
И в C:\MASM32\ тоже?
Автор: vjick
Дата сообщения: 06.03.2013 22:20
Поставил 2008 VS. Все ок.
Всем спасибо.
С MASM тоже разобрался ради общего развития.
Автор: inf158704
Дата сообщения: 07.03.2013 12:20

Код:
// ndis
VOID NdisInitializeString(PNDIS_STRING destination, PUCHAR source)
    {                            // NdisInitializeString

// Exported entry 136. NdisInitializeString
// Attributes: bp-based frame
// __stdcall NdisInitializeString(x, x)

//public _NdisInitializeString@8
//_NdisInitializeString@8    proc near


    _asm
        {
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch

mov    edi, edi
push    ebp
mov    ebp, esp
push    edi
mov    edi, [ebp+arg_4]
mov    eax, edi
lea    ecx, [eax+1]

loc_128C3:
mov    dl, [eax]
inc    eax
test    dl, dl
jnz    short loc_128C3
push    esi
mov    esi, [ebp+arg_0]
sub    eax, ecx
add    eax, eax
mov    [esi], ax
add    eax, 2
mov    [esi+2], ax
movzx    eax, ax
push    7473444Eh
push    eax
push    0

call    ExAllocatePoolWithTag
//call    ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

test    eax, eax
mov    [esi+4], eax
pop    esi
jz    short loc_1290B

loc_128F5:
mov    cl, [edi]
test    cl, cl
jz    short loc_12907
movzx    cx, cl
mov    [eax], cx
inc    edi
inc    eax
inc    eax
jmp    short loc_128F5

loc_12907:
and    word ptr [eax],    0

loc_1290B:
pop    edi
pop    ebp
retn    8
//_NdisInitializeString@8    endp
        }
    }                            // NdisInitializeString
Автор: bomzzz
Дата сообщения: 07.03.2013 13:08

Цитата:
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch


тут врядли имеется ввиду dword ptr[8], тут скорее всего имеется ввиду адреса относительно командной строки

наверно проще переписать это все на нормальный ассемблер
Автор: inf158704
Дата сообщения: 07.03.2013 13:22
беда в том что из меня програмист никакой, в лудшем случае по аналогии чтото могу поменять...
по задумке у меня не только одна эта асемблерная вставка должна быть...
поподробнне можно насчет адреса? хотябы примерчик какойто

//mov    esi, [ebp+arg_0]
...
mov    esi, [ebp+3]
заменяю аргументы просто на значения в принципе компилируеться...

правда была еще ошибка для проверки тоже закоментировал
//mov    ebp, esp
//pop    ebp
чем ему ebp ненравиться может? и всетаки почему аргументы непринимает

Автор: ne_viens
Дата сообщения: 07.03.2013 15:27
Это не самое лучшее решение- делать инлайн, так как компилятор выключает оптимизацию а под win64 инлайн вообще недоступен.
Лучше собирать куски asm кода в lib при помощи MASMа и потом линковать прогу с lib. Или сразу в уме (или при помощи Hexrays) на C переводить.


__stdcall NdisInitializeString(PNDIS_STRING destination, PUCHAR source)
{ // NdisInitializeString

// Exported entry 136. NdisInitializeString
// Attributes: bp-based frame
// __stdcall NdisInitializeString(x, x)

//public _NdisInitializeString@8
//_NdisInitializeString@8 proc near


_asm
{
;arg_0 = dword ptr 8
;arg_4 = dword ptr 0Ch

;mov edi, edi
;push ebp
;mov ebp, esp
;push edi
mov edi, source
mov eax, edi
lea ecx, [eax+1]

loc_128C3:
mov dl, [eax]
inc eax
test dl, dl
jnz short loc_128C3
;push esi
mov esi, destination
sub eax, ecx
add eax, eax
mov [esi], ax
add eax, 2
mov [esi+2], ax
movzx eax, ax
push 7473444Eh
push eax
push 0

call ExAllocatePoolWithTag
//call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

test eax, eax
mov [esi+4], eax
;pop esi
jz short loc_1290B

loc_128F5:
mov cl, [edi]
test cl, cl
jz short loc_12907
movzx cx, cl
mov [eax], cx
inc edi
inc eax
inc eax
jmp short loc_128F5

loc_12907:
and word ptr [eax], 0

loc_1290B:
;pop edi
;pop ebp
;retn 8
//_NdisInitializeString@8 endp
}
} // NdisInitializeString
Автор: bomzzz
Дата сообщения: 07.03.2013 16:24
а че эта вставка вообще делает, может проще просто написать с нуля?
Автор: inf158704
Дата сообщения: 07.03.2013 20:38
самое оптимальное решение это именно асемблерная вставка
обясню почему:
1. я пока 0 и в асемблере и в си,
2. это фунция ядра, в ХР она есть, оттуда я ее и вытащил... таких фунций мне нужно минимм еще штуки четыре.
3. на даном этапе мне чесно скажу безразницы что она делает имено интересует способы вставки и все.
4. ковыряюсь в чужом коде на СИ, 99 процентов коророго я непонимаю и думаю никогда неразберусь, но 1 процента мне достаточно, в этом 1 проценте полгода разбирался.
х64 тоже ненужен
всетаки подскажите имено где ошибка при определении констант как понимаю
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch
это именно константы... они должны хранится в область кода или данных? может имено это я неучитываю? хотя в принципе ида их из одласти кода и взяла
способ вставки отдельным файлом конечно интересен... былобы проще вставлять... но сейчас главное имено разобраться почему непринимает константы и чем ему регистр ebp немил
с call ExAllocatePoolWithTag разобрался все верно принимает именно так, хоть и странно


Цитата:
Лучше собирать куски asm кода в lib при помощи MASM

чем мне может помоч этот способ?
Автор: bomzzz
Дата сообщения: 07.03.2013 20:45

Цитата:
я пока 0 и в асемблере и в си,

наверно надо поставить задачу попроще и продвигаться будет легче, чем двигаться втемноте полной на догадках на 99% неправильных.
Автор: inf158704
Дата сообщения: 07.03.2013 20:52
код рабочий
могу бросить суюда если интересно он толко на СИ несовсем будет по теме
а слабо через INT21 прерывание написать?
Автор: bomzzz
Дата сообщения: 07.03.2013 20:55

Цитата:
.386

.model flat, stdcall
option casemap :none

include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\user32.inc
include \MASM32\INCLUDE\kernel32.inc
includelib \MASM32\LIB\user32.lib
includelib \MASM32\LIB\kernel32.lib

.data
mestitle    db "Hello",0
message        db "Hello World",0
.data?
buffer        db 512 dup(?)

.code
start:
invoke MessageBox,0,ADDR buffer,ADDR mestitle,MB_ICONASTERISK
invoke ExitProcess,0
end start

ввот рабочий код, разбери его скомпиль на масме и вперед
Автор: ne_viens
Дата сообщения: 07.03.2013 21:26

Цитата:

Цитата: Лучше собирать куски asm кода в lib при помощи MASM


чем мне может помоч этот способ?
Автор: inf158704
Дата сообщения: 07.03.2013 22:07
ne_viens
Тоесть проблему сохранения и востановления состояний регистров для амсемблерной вставки кампилятор берет на себя. Я вас правильно понимаю?
Вы действительно правы в таком случае, проще всего собирать код при линковке. Только вот у меня нет ни одного примера как это делать. И опыта работы с масмом пока нет.
Если можно подскажите чтобы мне можно было посмотреть для примера. Пока незнаю чем отличаеться компилячия в библиотеку от исполняемого файла.
Автор: vjick
Дата сообщения: 07.03.2013 22:54
bomzzz
почему кстати нельзя иклудить? у меня в VS 2008 все ок подхватывается - файлы с процедурками
Автор: bomzzz
Дата сообщения: 07.03.2013 22:57
ну может я ошибаюсь.
Автор: vjick
Дата сообщения: 07.03.2013 23:00
bomzzz
все ок инклудится. повыносил процедуры в отдельный файл. норм подхватываются но масм тоже понравился. в нем счас и пишу. менее громозкий, маленький и шустренький.
Автор: bomzzz
Дата сообщения: 07.03.2013 23:07
мне он самому понравился. большая удача, что я его случайно выбрал положившись на марку микрософта. сейчас бы с фасмом каким нибудь мучался
Автор: ne_viens
Дата сообщения: 07.03.2013 23:33
>inf158704

Да, о сохранении регистров компилятор позаботится.

Пример вызова куска asm кода из C:

1. Собираем obj файл из твоего примера выше с "ml /c ndis.asm"
Код надо чуть поправить:
;----------------------------------------------------
;ml /c ndis.asm
.486
.model flat, stdcall
option casemap:none
externdef ExAllocatePoolWithTag@12 ROC

.code
NdisInitializeString@8 proc C

    arg_0 = dword ptr 8
    arg_4 = dword ptr 0Ch
    
    mov edi, edi
    push ebp
...
call ExAllocatePoolWithTag@12
...
    retn 8

NdisInitializeString@8 endp
;----------------------------------------------------

2. Пишем прогу на C:
//===================================================
// cl linktest.c ndis.obj
#pragma comment(lib, "C:\\WinDDK\\7600.16385.1\\lib\\wxp\\i386\\ntoskrnl.lib")

typedef struct {
    short len;
    short len2;
    short* Name;
} UNICODE_STRING;


void __stdcall NdisInitializeString(UNICODE_STRING*, char*);

main()
{
    UNICODE_STRING str;
    char buf[16];
    
    NdisInitializeString(&str, buf);
}
//===================================================

3. Собираем C прогу вместе с ndis.obj "cl linktest.c ndis.obj"

Запустится она конечно незапустится, так как с ntoskrnl.exe слинкована, но идею понять можно.

Автор: inf158704
Дата сообщения: 13.03.2013 12:33
вопрос снял, нашел свою ошибочку, но пока некомпилируется до конца ошибка такая в логе

ndis.asm(81) : error A2088: END directive required at end of file
что значит пока непонимаю

retn    8
NdisInitializeString@8 endp
end NdisInitializeString@8
так компиляция проходит успешно, хорошобы мне только знать насколько это корректно

подскажите еще что значит @12 да и в принципе PROC для чего здесь
недолжно ли быть чтото типа этого:
externdef _imp__MessageBoxA@16:DWORD
MessageBox equ <_imp__MessageBoxA@16>
Автор: delover
Дата сообщения: 14.03.2013 08:00
Сорри за немного флуд.

Самый лучший ассемблер который я видел это компьютер ДВК. Он умел делать такие инструкции которых не умеет нынешний Pentium. Я имею ввиду типа

MOV AX, DI + [CX+DX+[EI+SP]]

Интересно ваксы сейчас умеют такое? Однажды человечество пошло путём интел.
Автор: bomzzz
Дата сообщения: 14.03.2013 08:46
если бы ему для этого нужно было пол такта, был бы повод для обсуждений. посмотри команду lea
Автор: akaGM
Дата сообщения: 14.03.2013 10:26
inf158704

Цитата:
подскажите еще что значит @12
где?
если здесь, то это для восстановления стека, "снять со стека @N байт":
Цитата:
retn 8
NdisInitializeString@8
Автор: ne_viens
Дата сообщения: 14.03.2013 10:47

Цитата:
ndis.asm(81) : error A2088: END directive required at end of file
что значит пока непонимаю

retn 8
NdisInitializeString@8 endp
end NdisInitializeString@8
так компиляция проходит успешно, хорошобы мне только знать насколько это корректно


Это значит, что я с ctrl-c, ctrl-v последнюю строчку не скопировал (END NdisInitializeString@8).


Цитата:

подскажите еще что значит @12 да и в принципе PROC для чего здесь
недолжно ли быть чтото типа этого:
externdef _imp__MessageBoxA@16:DWORD
MessageBox equ <_imp__MessageBoxA@16>


@12 - Это так называемая декорация названия функции.
У C функции добавляется "_" в начале, у __stdcall тоже добавляется "_" в начале а в конце "@" и число, которое равно количеству аргументов умноженное на 4, а C++ вообще кошмарные названия получаются.
Таким образом ndis.lib будет импортировать _ExAllocatePoolWithTag@12 из ntoskrnl.lib, a експортировать _NdisInitializeString@8, которую в свою очередь будет импортировать linktest.c Хексредактором можно посмотреть libы и называть ф-ии так, чтобы получался подсмотренный результат.

ROC - это просто ещё один способ вызвать внешнюю ф-ю.
В этом случае код будет:

CALL _jmp
_jmp:
JMP DWORD PTR[<&user32.MessageBoxA>]


А с TR сразу:

CALL DWORD PTR[<&user32.MessageBoxA>]


Автор: akaGM
Дата сообщения: 14.03.2013 13:04
ne_viens

Цитата:
У C функции добавляется "_" в начале, у __stdcall тоже добавляется "_" в начале а в конце "@" и число, которое равно количеству аргументов умноженное на 4
нет, ты ошибаешься, -- всё-таки _количество байт_, передаваемых в функу...

Код: void __stdcall test(double aa)
{
a = 20.;
}
void main() {
test(10.);
}
Автор: inf158704
Дата сообщения: 14.03.2013 13:16
насчет кода значения неимеет просто пример мне он более менее понятен...
а вот собрать 2 в одном я так и несмог
при cl linktest.c ndis.obj > txt.txt
ошибка
ndis.obj : error LNK2019: unresolved external symbol _ExAllocatePoolWithTag@12 referenced in function _NdisInitializeString@8
тут похоже как раз проблема с именами получаеться пока читаю но тут до макросов FAR аж дело дошло
получилось толко когда в linktest.c добавил следующее:

#pragma comment(lib, "C:\\WinDDK\\2600\\lib\\wxp\\i386\\ntoskrnl.lib")
#pragma comment(lib, "C:\\WinDDK\\2600\\lib\\wxp\\i386\\ndis.lib")
так собираеться линкером
если
#pragma comment(lib, "C:\\WinDDK\\2600\\lib\\wxp\\i386\\ndis.lib")
можно собрать чарез cl linktest.c без ndis.obj тотол командер правда показывает при этом что функции ndis нет в системе и файл получаеться 14кВ вместо 2 при первом варианте да и из kernel32 пытается кучу импорта получить...
поэтому вопрос задам глупый а что такого береться из библиотек?

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

Предыдущая тема: .NET GUI компоненты


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.