Problemy początkującego w NASM

0

Przed chwilą zacząłem naukę NASMa, uczę się stąd http://rudy.mif.pg.gda.pl/~bogdro/dos/a_kurs01.htm.
Fajny kurs, jedyny minus, że dla DOS-a, a nie Win32, ale poszukałem trochę o różnicach i myślę, że dam radę.
Pierwszy mój problem jest taki, że nie wiem jak dostać adres segmentu z danymi.

segment .data
	msg db "Hello world!$"
	
segment .code
main:
	mov ah, 9
	mov edx, msg
	mov eax, data
	mov ds, eax
	int 21h
	
	mov ah, 0
	int 16h
	
	mov ah, 4C00h
	int 21h

Ale nie działa, i nie mam zielonego pojęcia co wpisać zamiast data w instrukcji mov eax, data. Widziałem nawet gdzieś w manualu NASMa dokładnie takie samo coś, ale nie pamiętam gdzie to było.
Z góry dzięki i liczę na szybką pomoc.

0

DS jest rejestrem 16-biotowym, wiec nie mozesz kopiowac wartosci z EAX do niego.
Co do hello world to wyglada tak pod Linuksem, na Windowsa wystarczy zmienic przerwania, a offset otrzymujesz za pomoca odjecia od poczatku kodu, czyli $, etykiete, czyli adres i zapisujesz jako equ:

section .text
global _start
_start:
        xor     eax, eax
        mov     al, 0x4
        xor     ebx, ebx
        mov     bl, 1
        mov     ecx, msg
        mov     edx, lmsg
        int     0x80

        xor     eax, eax
        mov     al, 0x1
        xor     ebx, ebx
        int     0x80

section .data
        msg     db      "Hello world!"
        lmsg    equ     $ - msg
0

W przypadku generowania pliku *.com musisz brać pod uwagę to iż nie warto stosować żadnych segmentów czy sekcji ponieważ cały program jest zawsze umieszczany w jednym segmencie. Tak więc twój program powinien wyglądać tak:

org 0x100
        mov ah, 9
        mov dx, msg
        int 21h
       
        mov ah, 0
        int 16h
       
        mov ax, 4C00h
        int 21h

        msg db "Hello world!$"

Kompilowane nasm.exe -f bin nazwa_pliku.asm -o nazwa_pliku.com

W programach uruchamianych z plików *.com na wejściu zawsze masz rejestry CS i DS ustawione na ten sam segment.

0

I właśnie o to chodzi, że ja nie chcę .com!!! Win32 czyli .exe, z segmentami. </quote>

0

Do autora, widzisz ja Ci podalem kod jak to ma wygladac na Linuksie, zeby z tego miec exe pod windowsem zostawiasz szkielet, a zamieniasz przerwania na te co Nevar napisal i kompilujesz.
Twoj kod nie dziala, poniewaz nie ma nigdzie identyfikatora/symbolu o nazwie data oraz z drugiego powodu, ktory podalem w poscie wyzej.

0

Jak to nie ma? segment .data to co w takim razie jest?
Ale czekaj, powoli.

section .text
global _main
_main:	
	mov eax, msg
	
	mov ah, 4Ch
	int 21h
	
section .data
	msg db "Hello WOrld!$"

Dlaczego to po uruchomieniu się zawiesza?

0

I w ogóle opis tego przerwania jest taki: AH = 09h
DS:DX -> '$'-terminated string

Więc nic mi nie da przekopiowanie tego adresu do rejestru edx
0

Znaczy się tak to miało być:
Under the FlashTek X-32 DOS extender, the pointer is in DS:EDX
Więc coś do teog DS muszę przesunąć.
</asm>

0
section .text
global _start
_start:
        xor     eax, eax
        mov     ah, 9
        xor     ebx, ebx
        mov     bl, 1
        mov     edx, msg
        mov     edx, lmsg
        int     21h

        xor     eax, eax
        mov     ax, 4C00h
        xor     ebx, ebx
        int     21h

section .data
        msg     db      "Hello world!"
        lmsg    equ     $ - msg

Takie coś nie działa.

0

Dobra, zalogowałem się, żeby już tak nie spamować, teraz będę edytował.

Chyba coś robię źle, bo nawet takie coś:

section .text
global _start
_start:
        mov     ax, 4C00h
        int     21h

section .data

Nie działa...

0

Jeżeli chodzi o pliki *.exe dosowe to bezpośrednio NASM takich nie wygeneruje. Musisz sobie ściągnąć dodatkowo linker. http://alink.sourceforge.net/download.html

Kod programu:

segment .data
        msg db "Hello world!$"

segment .code
..start:
        mov ax, data
        mov ds, ax

        mov edx, msg
        mov ah, 9
        int 21h
       
        mov ah, 0
        int 16h
       
        mov ax, 4C00h
        int 21h

Na początek kompilujesz:
nasm.exe -f obj nazwa_pliku.asm -o nazwa_pliku.obj
potem linkujesz
alink.exe nazwa_pliku.obj -oEXE -o nazwa_pliku.exe

0

Używałem ld i -f elf w nasmie
Tylko jest taki problem, że nie uruchamia mi się to na Win7 x64.

0

Kurde no, ładnie się kompiluje, ale jak próbuję uruchomić to co napisałeś, to:

Wersja d:\Michal\NASM\prog.exe nie jest zgodna z wersja uruchomionego systemu Wi
ndows. Sprawdz w informacjach dotyczacych systemu operacyjnego na tym komputerze
, jaka wersja programu jest potrzebna (x86 - 32-bitowa czy x64 - 64-bitowa), a n
astepnie skontaktuj sie z wydawca oprogramowania.

Da się jakoś alinkiem zrobić 32bitową aplikację?

0

Na 64 bitowych jest troche inaczej z asemblerem, ale niestety nie mam takiego procka, wiec niewiem jak to zrobic.
Zobacz to:
http://www.nasm.us/doc/nasmdoc7.html#section-7.6
oraz zobacz, czy masz wersje NASM przynajmniej 2.0, bo starsze nie generuja 64 bitowego kodu.

0

hck, zdecyduj się, czy chcesz pisać pod 32-bitowego DOS-a, czy pod Win32. Jeśli to drugie, to na pewno nie możesz używać DOS-owych przerwań (tzn: mogą jakimś cudem działać, ale wcale nie muszą).

0

Wiele mi wyjaśniłeś, dzięki!

Czyli teraz zamiast przerwania AH 9, 21h muszę użyć printfa?
W jakim dll'u jest ta funkcja?

0
#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
 if(argc != 3)
   return 0;

 HMODULE hlib = LoadLibrary(argv[1]);
 FARPROC addr = GetProcAddress(hlib, argv[2]);

 printf("%x\n", (int)addr);

 return 0;
}

Jako pierwszy parametr dajesz nazwe biblioteki, a jako drugi nazwe funkcji, jesli funkcja jest w tej bibliotece to bedziesz mial adres, jesli nie to zobaczysz 0 na konsoli.
Szukaj glownie w:
kernel32.dll
user32.cll
msvcrt.dll <- tu pewnie jest printf

0

Jak nie masz ASLR to mozesz dzieki temu kodowi co wyzej, wywolywac funkcje z libow, znajac ich adresy, poniewaz przewaznie sa i tak te glowne liby zamapowane gdzies w pamiec.

Dla MessageBoxA bedzie cos takiego:

section. text
global _start
_start:
  xor eax, eax                       <- od konca wrzucasz parametry funkcji na stos
  push dword [eax]

  jmp getstraddr:

wroc:
  pop esi
  push dword [esi]
  push dword [esi]
  xor eax, eax                        <- z tego co pamietam MB_OK to zero
  push dword [eax]
  mov ebx, 0x38748374 <- adres funkcji
  call ebx

getstraddr:
  call wroc
  db "Hello Wordl",0x0
0

A co z tym co funkcje zwracają?

0

w eax

0

Odpaliłem ten program, wyszukałem printf w msvscrt i jej adres to 76c5c5b9.
Więc napisałem:

segment .code 
global _start
_start:	
	mov ebx, 0x76c5c5b9
	push msg
	call ebx
	ret
	
segment .data
        msg db "msg",0

Ale się wysypuje.
Tak samo twój kod nie działa.

0

Moj kod nie dziala, bo adres jest zly oraz przy jmp, nie powinno byc dwukropka(machnalem sie nie chcacy) oraz napisalem, ze nie mozesz miec ASLR, zeby dzialalo.
Po kolejne, to printf potrzebuje dwoch argumentow, poniewaz jest to sformatowane pisanie na wyjscie, wiec musisz dac najpierw na stos adres stringa, adres zdobedziesz tak jak w moim przykladzie oraz jako druga wartosc na stos idzie ciag formatujacy ;)

1

Nie, no to za dużo bawienia się.
Znalazłem taką bibliotekę WIN32.lib dla NASMa no i MessageBox ładnie z niej działa, próbowałem podlinkować msvcrt.lib, ale alink nie znajduje tam printfa.

HELL YEAH!
Poradziłem sobie, a zrobiłem tak.

  1. Zmieniłem linker na polink, chociaż zwykłego linka pewnie też mógłbym użyć.
  2. Używając dumpbin wypatrzyłem, że w msvcrt.lib printf exportuje się jako __cprintf
    I wulała, wszystko działa.

Jak ktoś chce, daję kod.

extern __cprintf
section .code
global _start
_start:
	
	mov edx, msg
	mov ecx, ciag
	
	push edx
	push ecx
	call __cprintf
	
	pop ecx
	pop edx
	xor edx, edx
	xor ecx, ecx
	ret
	
section .data
	msg db "Hello world!",0
	ciag db "%s",0

Kompilowane:

nasm -f win32 -o prog.obj prog.asm
polink /ENTRY:_start /SUBSYSTEM:console /MACHINE:x86 prog.obj msvcrt.lib

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.