Flat assembler - najprostszy program 32-bitowy/64-bitowy

0

Zacząłem uczyć się asemblera korzystając z flat assemblera.

user image

Chodzi teraz o to, że gdy po kompilacji chcę go uruchomić to pokazuje mi się w/w monit o tym, że jest to aplikacja 16-bitowa.
Jak w sposób jak najmniejszy przerobić ten program aby pozostał nadal programem konsolowym (na okienkowe przyjdzie czas) i dał się skompilować (pod FASMem) i uruchomić na moim systemie: Windows 7 64-bit, architektura procesora: x86-64.

format binary
org 100h
start:
     mov  ah, 9
     mov  dx, info
     int  21h

     mov  ah, 0
     int  16h

     mov  ax, 4C00h
     int  21h

info      db  "Czesc.$"
0
int  21h

O ile mi wiadomo, int jest niedozwolone od Visty (wywali privileged instruction)...
Może w DOSBox'ie spróbuj?

0

Na współczesnych Windowsach nie ma już obsługi NTVDM (Virtual Dos Machine) ze względów bezpieczeństwa. Jak chcesz odpalić jakiś program dosowy to pozostają emulatory/symulatory.

0

To niech będzie Windowsowy byle konsolowy. Nie chodzi mi o emulowanie DOSa bo gdy przejdę na pisanie pod Win32 to problem znów się pojawi. Chodzi mi o jakiś szkielet konsolowego programu Win32, który mógłbym rozbudowywać i uczyć się asemblera.

0

Rozumiem, że chodzi Ci o pisanie aplikacji konsolowych pod Windows w assemblerze. Do tego musisz ściągnąć FASM for windows. Szkielet takiego programu masz tutaj//stackoverflow.com/questions/2540478/how-can-i-go-about-writing-to-the-console-in-fasm

0

ZTCP to w samym FASMie są przykłady, FASM for DOS powinien zawierać przykłady pod DOS, FASM for Linux przykłady dla Linuksa, FASM for Windows dla Windowsa, itd

0

O ile mi wiadomo, int jest niedozwolone od Visty (wywali privileged instruction)...
W aplikacjach Win32 - być może, tu mowa o DOS-owej…

Na współczesnych Windowsach nie ma już obsługi NTVDM (Virtual Dos Machine) ze względów bezpieczeństwa.
Nie tyle „współczesnych” co 64-bitowych, co zresztą jasno opisuje komunikat.
64-bitowy XP nie miał NTVDM, a 32-bitowy Windows 8 ma.

To niech będzie Windowsowy byle konsolowy
Przykładów jest dużo, wystarczy pogóglać.

np. http://forums.codeguru.com/showthread.php?355607-Making-a-Win32-NASM-app

0
Wibowit napisał(a):

ZTCP to w samym FASMie są przykłady, FASM for DOS powinien zawierać przykłady pod DOS, FASM for Linux przykłady dla Linuksa, FASM for Windows dla Windowsa, itd
Wszystko fajnie pięknie tylko, że:
Po pierwsze: Przykłady owszem są tylko dla Win64. Dla Win32 nie ma ani jednego. W dodatku są tak rozbudowane, że sam jako początkujący programista asma nie wiedziałbym co można jeszcze wyrzucić a co już nie.
Po drugie: Są to przykłady okienkowe, a jak napisałem w pierwszym poście chodzi mi o przykład szkieletu dla programu konsolowego.
Po trzecie: W Internecie rzeczywiście dużo jest przykładów ale większość dla MASMa albo NASMa. Poza tym do tej pory nie spotkałem jeszcze przykładu samego szkieletu programu, tzn. takiego, który jedynie co by robił to poprawnie zakończył. Wszystkie już coś tam robią.

Ale jest i dobra wiadomość. Poszukałem jeszcze raz i znalazłem to o co mi chodziło na tej stronie: http://jakash3.wordpress.com/2010/07/23/fasm-tutorial-16-32-bit/ , (ponadto nawiązałem znajomość z programistą FASMa który napisał mi co mogę z tych kodów usunąć aby rzeczywiście był to sam szkielet). Ale dziękuję wszystkim za odpowiedzi i rady.

0

Użyj loadera Gynvaela.
http://gynvael.coldwind.pl/?id=387

0

Poza tym do tej pory nie spotkałem jeszcze przykładu samego szkieletu programu, tzn. takiego, który jedynie co by robił to poprawnie zakończył. Wszystkie już coś tam robią.

Masz swój nicnierobiący program. NASM, choć pewnie w FASM będzie tak samo:

[segment .text]
[global main]

main:
    ret

``` C:\pp\myprogs\asm>nasm -fwin32 a.asm

C:\pp\myprogs\asm>link a.obj /entry:main
Microsoft (R) Incremental Linker Version 11.00.50929.0
Copyright (C) Microsoft Corporation. All rights reserved.

C:\pp\myprogs\asm>a

C:\pp\myprogs\asm>


EDIT: miało być „poprawnie zakończył”. O ile powyższy na pewno się kończy, nie jestem pewien co się dzieje z kodem wyjścia z programu. Na wszelki wypadek:

```asm
[segment .text]
[global main]

extern _ExitProcess@4

main:
    push 0
    call _ExitProcess@4
0
Azarien napisał(a):

choć pewnie w FASM będzie tak samo

Raczej nie tak samo. Składnia jest inna: http://rudy.mif.pg.gda.pl/~bogdro/dos/fntasm.htm
Ale jak już napisałem, poradziłem sobie z problemem.

0

Po pierwsze: Przykłady owszem są tylko dla Win64. Dla Win32 nie ma ani jednego. W dodatku są tak rozbudowane, że sam jako początkujący programista asma nie wiedziałbym co można jeszcze wyrzucić a co już nie.

Ściągnąłem FASM for Windows, a konkretnie fasmw17003.zip i w katalogu /EXAMPLES są przykłady dla Win32. Dodatkowo w i tylko w /EXAMPLES/WIN64 są przykłady dla Win64.

Po drugie: Są to przykłady okienkowe, a jak napisałem w pierwszym poście chodzi mi o przykład szkieletu dla programu konsolowego.

Program konsolowy różni się od okienkowego tym, że konsolowy ma domyślnie otwartą konsolę. W FASMie zamiast format PE GUI na starcie daje się format PE console i już się ma program tzw konsolowy.

Do wyciągnięcia uchwytów standardowego wejścia/ wyjścia/ wyjścia błędów masz GetStdHandle: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx

Zarówno w aplikacjach konsolowych jak i okienkowych możesz używać tych samych funkcji.

Po trzecie: W Internecie rzeczywiście dużo jest przykładów ale większość dla MASMa albo NASMa. Poza tym do tej pory nie spotkałem jeszcze przykładu samego szkieletu programu, tzn. takiego, który jedynie co by robił to poprawnie zakończył. Wszystkie już coś tam robią.

No to wytnij całą logikę i zastąp ją wywołaniem ExitProcess(0) z kernel32.dll.

0

Jeszcze tylko napisz, że te przykłady z katalogu: /EXAMPLES/WIN64 są wręcz idealne do rozpoczęcia nauki asemblera.

----- Edit -----

Wibowit napisał(a):

W FASMie zamiast format PE GUI na starcie daje się format PE console i już się ma program tzw konsolowy.
Trzeba było tak napisać w poprzednim poście. A skąd mam to wiedzieć? Gdybym to wiedział to bym się nie pytał. Po to jest (chyba) to forum.

0

Jak chcesz zacząć od Win32 to zacznij od Win32, a nie narzekaj, że są dodatkowo przykłady dla Win64. Jak cię tak bardzo drażnią to je wywal. Proste.

Najprostszy przykład to chyba /EXAMPLES/HELLO, gdzie cała magia jest upchana do nagłówków i zaimportowane są standardowo funkcje kilku najczęściej używanych bibliotek.

Dla Win32 są świetne tutoriale Iczeliona, dostępne np tutaj: http://edu.i-lo.tarnow.pl/inf/prg/002_winasm/index.php ale niestety są pod MASMa, a nie FASMa. Jeśli jesteś początkujący to tłumaczenie MASM -> FASM będzie raczej sprawiać na początku problem.

W asemblerze możesz zrobić co najmniej wszystko to co da się zrobić w C/ C++, więc możesz też rozkminić jak jest kompilowany kod C/ C++ do asemblera i pouczyć się Win32 z tutoriali dla C/ C++. No ale to trudniejsza droga.

0
  1. aplikacji dosowej nie uruchomisz na 64bitoej platformie.
  2. Jeżeli chcesz napisać program konsolowy pisanie kodu w fasm rozpoczynasz od dyrektywy "format pe console" jak niżej (najprostrzy program który nic nie robi):
format pe console
ret
  1. Zapewne chcesz coś wyświetlić ... w twoim przypadku będzie to wyglądało tak:
format pe console
entry start
include 'win32ax.inc'
section '.import' import data readable
library msvcrt, 'msvcrt.dll'
import msvcrt,\
       printf,'printf',\
       system,'system'

section '.code' code readable writeable executable
start:
        cinvoke    printf, 'hello world'
        cinvoke    system,'pause'
        ret                    

Teraz po kolei i bardzo pobieżnie wyjaśnienie co się dzieje.

  • entry start: w tej linijce ustanawiasz entry point programu - każdy plik wykonalny ( plik formatu PE ) go posiada. Entry point czyli punkt (adres) od którego program ma się rozpocząć.
  • include 'win32ax.inc' - załączenie tego pliku nagłówkowego umożliwia korzystanie z różnych "udogodnien" takich jak użyte tutaj macro "cinvoke" co poprawia czytelność kodu - ważne dla początkującego ale nie tylko
  • section - dyrektywa określająca początek nowej sekcji po nie następuje nazwa w cudzysłowie - dowolna może być "" i też będzie dobra - po nazwie mamy atrybuty sekcji w pierwszej - sekcja importu do odczytu w drugiej mamy atrybuty informujące, że znajduje się tam kod programu oraz, że sekcja (jej zawartość) może być czytana zapisywana oraz wykonywana - bo przecież jest to nasz kod w kocu.
  • library - makrodefinicja upraszczająca kożystanie z dowolnej biblioteki istniejącej w systemie - w naszym przypadku potrzebujemy wyświetlić napis na ekran. Znam jedną taką funkcję i wiem, że jest ona "zawarta" (uproszczenie) w bibliotece MSVCRT.DLL więc mamy:
    library msvcrt, 'msvcrt.dll' co oznacza, że bibliotekę znaną w systemie jako msvcrt.dll będę nazywał od tąd msvcrt.
  • import - również macrodefinicja upraszczająca "pozyskiwanie"(uproszczenie grube) odpowiednich procedur, funkcji z określonej biblioteki"
    import msvcrt,
    printf, 'printf' oznacza, że z biblioteki którą nazywam w programie msvcrt importuję funkcje o nazwie printf i tak też będę ją nazywał (mogę innaczej ale po co
    bałagan).

dalej mamy sekcję kodu oraz etykietę start czyli nasz entry point jedziemy dalej ... myślę, że po uruchomieniu kodu nie trzeba właściwie tego tłumaczyć będzie jasne.
Jak czegoś nie wiesz dawaj śmiało.

0

Po trzecie: W Internecie rzeczywiście dużo jest przykładów ale większość dla MASMa albo NASMa.

Tak wiem .. i jżeli się im przyglądniesz to bardzo często okazuje się, że to jeden i tem sam kurs przeklepany z innego języka lub strony jak lo.tarnów z angielskiego języka po prostu żywcem przeklepany i dodane pożal się boże przykłady w pascalu

0

To coś na lo.tarnów to polskie tłumaczenie legendarnego tutorialu Iczeliona. Ja uczyłem się z oryginału, miałem wtedy neta modemowego i chodziłem chyba jeszcze do podstawówki, albo byłem na początku gimnazjum. Sam tutorial ma chyba z 10 lat już i jest nieco przestarzały, opisuje zresztą samo WinAPI, które samo w sobie jest stare. No ale od czegoś trzeba zacząć.

0

No tak dokładnie to bardzo stary tutorial (w orginale) ciekawe gdzie ci wszyscy tłumacze byli gdy coś takiego było potrzebne (przynajmniej mnie) w polskiej wersji językowej - po nastu latach nawet nikt z nich się nie "rzucił" na temat zmiany chociażby składni tylko dalej przeklepują to w masmie tak jak było ...

Co do autora tematu - z serwisu o którym wspomniałeś http://rudy.mif.pg.gda.pl/~bogdro/ są rozdziały do których powinieneś wrócić ponieważ nie znajdziesz lepszego opisu w języku pl. są to:

  • rozdział "operacje na bitach"

  • rozdział "operacje na łańcuchach znaków"

  • wytłumaczenie stosu (niepamiętam nazwy rozdziału) - nie ma lepszego wytłumaczenia proste i jasne jak słoneczko.
    te 3 tematy rozdziały są niezależne od systemu DOS, WINDOWS, LINUX zawsze działają i są to takie same podstawy jak MOV.
    Jednak na początku nie ma sensu wkuwać ich na pamięć - przeczytaj i zapamiętaj, że te informacje tam są, zapisz w zakładki - podczas nauki asma co chwile będziesz tam musiał zaglądać ale inaczej chyba się nie da :)

  • resztę wraz z przykładami sobie daruj ponieważ to jest tylko dla DOS'owych programów których nie uruchomisz na 64b windzie (oprócz MMX oraz FPU ale to nie jest dobre na początek)

0

Dziękuję za wszystkie uwagi i wskazówki. Jeszcze mam jedno pytanie. Generalnie jeżeli chodzi o ten "najprostszy program" to nie chodzi mi o to, żeby wypisywał cokolwiek (np. liczbę z jakiegoś rejestru na ekran) z tego powodu, że na razie chcę się nauczyć, dialektu procesora, poznać instrukcje i rejestry, etc. Do sprawdzania tego co jest aktualnie w rejestrach i flagach używam na razie debugera FDBG - wiele o nim czytałem na forach, jest okienkowy, napisany w FASMie (czyli w tym w czym się uczę pisać) i generalnie przypadł mi do gustu. Ale w czym rzecz. Debuguje on programy 64-bitowe (tzn. być może 32 też ale na razie nie udało mi się zdebugować ani jednego programu Win32). Zatem jestem zmuszony pisać dla Win64. Generalnie nie jest to jakimś problemem bo instrukcje się nie zmieniają, dochodzi tylko kilka nowych rejestrów. I mam jeszcze jedno w związku z tym pytanie. Na stronie:
http://board.flatassembler.net/topic.php?t=14034 (drugi post od dołu) jest pokazany przykład prostego programu Win64. Ale jest on okienkowy. Czy moglibyście mi podać dość prosty program pod Win64? Może być np. ten sam wypisujący "Hello World!" ale nie w okienku ale w konsoli. Z tym, że na razie zamiast invoke/cinvoke uczę się używać instrukcji call. Na tej stronie którą podałem wykorzystana jest właśnie ta funkcja (wiem, że korzystanie z invoke byłoby prostsze ale na razie chcę się nauczyć pisać korzystając ze względnie elementarnych rozkazów, a korzystać z makr czy procedur gdy to jest już bezwzględnie konieczne).

Z góry dziękuję za odpowiedź. Chociaż odczuwam, że chyba za bardzo Was męczę w tym wątku. Ale naprawdę zależy mi aby poznać asemblera.

Pozdrawiam
Krzysztof

0

Może być np. ten sam wypisujący "Hello World!" ale nie w okienku ale w konsoli.

O tym, czy program będzie konsolowy czy okienkowy, decyduje linker – na pewno jest od tego odpowiednia opcja.

Pisanie do konsoli: GetStdHandle i WriteConsole, albo za pomocą CreateFile podając "CON" jako nazwę pliku, a potem WriteFile.
Albo, najprościej, z msvcrt.dll zaimportować funkcję printf()

0

Niedługo będzie 2 lata jak bawię się fasmem (najpierw 16b) i wciąż uważam, że jest za wcześnie na 64b ale każdy po swojemu powinien atakować problem. Tutaj masz na forum fasma przykład:
http://board.flatassembler.net/topic.php?t=11319
spróbuj. No co do korzystania z makr to nawet sam początek powiedzmy

format pe console 

lub

format PE64 console

to jest swego rodzaju uproszczenie jeżeli nie chcesz z tego korzystać to twój kod musiał by mieć powiedzmy taką postać:
http://board.flatassembler.net/topic.php?t=14641
musiał byś ręcznie wszystkie nagłówki formatu PE wypełnić ... no można tylko po co.
makrodefinicje typu invoke, cinvoke, fastcall (w przypadku x64) są "nieszkodliwymi" uproszczeniami tzn takimi które nie powodują, nie mają żadnego wpływu na szybkość wykonania kodu za to rewelacyjnie poprawiają jego czytelność. Oczywiście nie zawsze można ich użyć i należy wiedzieć jak działają ponieważ niekiedy trzeba np pobrać adres funkcji ręcznie np:

...
section '.code' code readable writeable executable
        text                      db      'example',0

start:
        invoke  LoadLibrary, 'user32.dll'
        invoke  GetProcAddress, eax, 'MessageBoxA'

        push    MB_YESNO
        push    text
        push    text
        push    HWND_DESKTOP
        call     eax
        ret         

To samo się tyczy sekcji importu - można ją ręcznie wypełniać z tym, że moim zdaniem zwłaszcza na początku nie ma co sobie zaciemniać obrazu - podam przykład:
50 raz od nowa próbujesz napisać programik np konwersji prezentacji danych z HEX na DEC ... i co za każdym razem będziesz wklepywał sekcję importu ręcznie, wypełniał nagłówki PE ... no oczywiście można a nawet kilka razy w życiu trzeba ale nie więcej i nie na początku nauki- takie jest moje zdanie.

Odnośnie debugera o którym piszesz luknołem i faktycznie wygląda na to, że jest tylko dla 64b. Jednak pobierz sobie AIDA Pro x86 - bardzo czytelny jest... ale nie używając debugera nie jesteś skazany na to żeby pisać 64b programy ... no ja w ogóle nie wiedziałem co to debuger na początku a trzeba było wiedzieć co jest w rejestrach co w pamięci, napisałem sobie pewną funkcję + macro które ją wywołuje i do dzisiaj z tego korzystam :) dużo bardziej poręczne niż analiza tego co wypluwa debager. Tutaj masz link do pliku codehelp.inc :
http://download.hellshare.pl/kodowanie/codehelp-rar/9407595/
możesz go użyć w ten sposób:

format pe gui 4.0
entry start
include   'win32ax.inc'
include   'codehelp.inc'      ; w ten sposob includujesz plik który ci podsyłam 

section '.code' code readable writeable executable 

        wartosc                   dd      0FFFFFFFFh 
start:
        show                  dword  [wartosc], 'wartosc'
        mov                   eax, 01
        show                  eax, 'zawartosc rejestru eax'
        show                  start, 'virtualny adres etykiety start:'
        show                  RVA start, 'relatywny adres etykiety start:'
        show                  (start - RVA start), 'ImageBase:' 
        invoke                GetFileAttributes, 'c:\nie ma takiego pliku.exe'
        SHOWERROR             'Funkcja get GetFileAttributes() zakonczyla sie błędem:'
        ret       

Jak widzisz plik ten zawiera również macrodefinicje SHOWERROR - również bardzo pomocna jest.

W ogóle to podstawowy problem jaki spotykają wszyscy na początku nauki asma "jak zobaczyć co jest w rejestrach, co w pamięci" dla tego wrzucam ten plik.

PS. Gdzieś widziałem na jakimś forum wyrażenie "dzieci invoke" (pogardliwie). No jakoś nie potrafię znaleźć uzasadnienia dla czego niby tego nie stosować ??? nie mam zajawek grafomańskich ani masochistycznych więc po co sobie utrudniać życie. Ogólnie uważam, że to cecha nowoczesnych asemblerów, że niektóre prace wykonuje za nas kompilator na szczęście od jakiegoś czasu okienkowy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1