Schauen Sie sich auch Steve Gibsons Starterkit für die Montage von Small Is Beautiful- Fenstern an.
Jeremy
Die Nichtverwendung von C-Bibliotheken ist eine etwas seltsame Einschränkung. Man muss eine Bibliothek innerhalb des MS-Windows-Betriebssystems aufrufen. wahrscheinlich kernel32.dll. Ob Microsoft dies in c oder Pascal geschrieben hat, scheint irrelevant. Bedeutet dies, dass nur vom Betriebssystem bereitgestellte Funktionen aufgerufen werden können, was in einem Unix-System als Systemaufrufe bezeichnet werden würde?
Albert van der Horst
Bei C-Bibliotheken geht er vermutlich ohne C-Laufzeitbibliotheken aus, wie sie mit GCC oder MSVC geliefert werden. Natürlich muss er oder sie einige Standard-Windows-DLLs wie kernel32.dll verwenden.
Rudy Velthuis
2
Die Unterscheidung zwischen kernel32.dll und einer gcc-Laufzeitbibliothek erfolgt nicht im Format (beide sind dll) und nicht in der Sprache (beide sind wahrscheinlich c, aber das ist verborgen.) Der Unterschied besteht zwischen vom Betriebssystem bereitgestellten oder nicht.
;----------------------------------------------------------------------------; helloworld.asm;;Thisis a Win32 console program that writes "Hello, World" on one line and;then exits.It needs to be linked with a C library.;----------------------------------------------------------------------------global _main
extern _printf
section .text
_main:
push message
call _printf
add esp,4
ret
message:
db 'Hello, World',10,0
16-Bit-Code mit MS-DOS-Systemaufrufen: Funktioniert in DOS-Emulatoren oder in 32-Bit-Windows mit NTVDM-Unterstützung . Kann unter 64-Bit-Windows nicht "direkt" (transparent) ausgeführt werden, da ein x86-64-Kernel den VM86-Modus nicht verwenden kann.
Die Frage erwähnt ausdrücklich "ohne Verwendung von C-Bibliotheken"
Mehrdad Afshari
25
Falsch. Die C-Bibliothek selbst kann es offensichtlich, also ist es möglich. Tatsächlich ist es nur etwas schwieriger. Sie müssen nur WriteConsole () mit den richtigen 5 Parametern aufrufen.
MSalters
12
Obwohl das zweite Beispiel keine C-Bibliotheksfunktion aufruft, ist es auch kein Windows-Programm. Die virtuelle DOS-Maschine wird ausgelöst, um sie auszuführen.
Rômulo Ceccon
7
@Alex Hart, sein zweites Beispiel ist für DOS, nicht für Windows. Unter DOS beginnen die Programme im winzigen Modus (.COM-Dateien, unter 64 KB Gesamtcode + Daten + Stapel) bei 0x100h, da die ersten 256 Bytes im Segment von der PSP belegt werden (Befehlszeilenargumente usw.). Siehe diesen Link: en.wikipedia.org/wiki/Program_Segment_Prefix
zvolkov
7
Dies ist nicht das, wonach gefragt wurde. Das erste Beispiel verwendet die C-Bibliothek und das zweite ist MS-DOS, nicht Windows.
Paulo Pinto
127
Dieses Beispiel zeigt, wie Sie direkt zur Windows-API wechseln und keine Verknüpfung in der C-Standardbibliothek herstellen.
Sie müssen wahrscheinlich die kernel32.lib einbinden, um dies zu verknüpfen (ich habe es getan). Link / Subsystem: Konsole / Nodefaultlib / Eintrag: main hello.obj kernel32.lib
Zach Burlingame
5
Wie verknüpfe ich das Objekt mit ld.exe von MinGW?
Dies sind Win32- und Win64-Beispiele mit Windows-API-Aufrufen. Sie sind eher für MASM als für NASM, aber sehen Sie sie sich an. Weitere Details finden Sie in diesem Artikel.
Dies verwendet MessageBox, anstatt auf stdout zu drucken.
Win32 MASM
;---ASM HelloWorldWin32MessageBox.386.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
title db 'Win32',0
msg db 'Hello World',0.code
Main:
push 0; uType = MB_OK
push offset title ; LPCSTR lpCaption
push offset msg ; LPCSTR lpText
push 0; hWnd = HWND_DESKTOP
call MessageBoxA
push eax ; uExitCode =MessageBox(...)
call ExitProcessEndMain
Win64 MASM
;---ASM HelloWorldWin64MessageBox
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
.data
title db 'Win64',0
msg db 'Hello World!',0.code
main proc
sub rsp,28h
mov rcx,0; hWnd = HWND_DESKTOP
lea rdx, msg ; LPCSTR lpText
lea r8, title ; LPCSTR lpCaption
mov r9d,0; uType = MB_OK
call MessageBoxAadd rsp,28h
mov ecx, eax ; uExitCode =MessageBox(...)
call ExitProcess
main endp
End
Verwenden Sie dies für die ausführbare 32-Bit-Datei, um diese mithilfe von MASM zusammenzustellen und zu verknüpfen:
Warum muss x64 Windows vor a 28 Stunden Byte Stapelspeicher reservieren call? Das sind 32 Byte (0x20) Schattenraum, auch bekannt als Heimatraum, wie es die aufrufende Konvention vorschreibt. Und weitere 8 Bytes, um den Stapel um 16 neu auszurichten, da die Aufrufkonvention erfordert, dass RSP 16 Byte vor a ausgerichtet ist call. ( mainDer Anrufer von Our (im CRT-Startcode) hat dies getan. Die 8-Byte-Rücksprungadresse bedeutet, dass RSP beim Eintritt in eine Funktion 8 Byte von einer 16-Byte-Grenze entfernt ist.)
Der Schattenraum kann von einer Funktion verwendet werden, um ihre Registerargumente neben den Stapelargumenten (falls vorhanden) abzulegen. A system callbenötigt 30 Stunden (48 Bytes), um zusätzlich zu den zuvor erwähnten 4 Registern auch Platz für r10 und r11 zu reservieren. DLL-Aufrufe sind jedoch nur Funktionsaufrufe, selbst wenn sie syscallAnweisungen umschließen .
Unterhaltsame Tatsache: Nicht-Windows, dh die x86-64-System V-Aufrufkonvention (z. B. unter Linux) verwendet überhaupt keinen Schattenraum und verwendet bis zu 6 Ganzzahl- / Zeigerregister-Argumente und bis zu 8 FP-Argumente in XMM-Registern .
Mit der MASM- invokeDirektive (die die Aufrufkonvention kennt) können Sie ein ifdef verwenden, um eine Version davon zu erstellen, die als 32-Bit oder 64-Bit erstellt werden kann.
ifdef rax
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
else.386.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
endif
.data
caption db 'WinAPI',0
text db 'Hello World',0.code
main proc
invoke MessageBoxA,0, offset text, offset caption,0
invoke ExitProcess, eax
main endp
end
Die Makrovariante ist für beide gleich, aber Sie werden das Zusammenbauen auf diese Weise nicht lernen. Sie lernen stattdessen Asm im C-Stil. invokeist für stdcalloder fastcallwährend cinvokeist für cdecloder variables Argument fastcall. Der Assembler weiß, welche er verwenden soll.
Sie können die Ausgabe zerlegen, um zu sehen, wie invokeerweitert.
+1 für deine Antwort. Können Sie bitte auch Assembler-Code für Windows unter ARM (WOA) hinzufügen?
Annie
1
Warum benötigt rsp 0x28 Bytes und nicht 0x20? Alle Referenzen auf der Aufrufkonvention besagen, dass es 32 sein sollte, aber es scheint in der Praxis 40 zu erfordern.
Douggard
In Ihrem 32-Bit-Nachrichtenfeldcode treten aus irgendeinem Grund titleFehler auf, wenn ich ihn als Beschriftungsnamen verwende. Wenn ich jedoch etwas anderes als Markennamen verwende mytitle, funktioniert alles einwandfrei.
user3405291
Wie geht das ohne?
Bluejayke
13
Flat Assembler benötigt keinen zusätzlichen Linker. Dies macht die Assembler-Programmierung ziemlich einfach. Es ist auch für Linux verfügbar.
Dies ist hello.asmaus den Fasm-Beispielen:
include 'win32ax.inc'.code
start:
invoke MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
invoke ExitProcess,0.end start
wo path_to_link könnte C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC \ ist oder wo auch immer Ihr link.exe Programm in Ihrer Maschine,
path_to_libs könnte C: \ Program Files (x86) \ Windows - Kits \ 8.1 \ Lib \ winv6.3 \ um \ x64 oder wo immer sich Ihre Bibliotheken befinden (in diesem Fall befinden sich sowohl kernel32.lib als auch user32.lib an derselben Stelle, andernfalls verwenden Sie eine Option für jeden Pfad, den Sie benötigen) und / largeaddressaware: Keine Option notwendig, um zu vermeiden, dass Linker sich zu lange über Adressen beschweren (in diesem Fall für user32.lib). Wenn hier der Linker von Visual über die Eingabeaufforderung aufgerufen wird, muss die Umgebung zuvor eingerichtet werden (einmal vcvarsall.bat ausführen und / oder MS C ++ 2010 und mspdb100.dll anzeigen)).
Ich empfehle dringend, default reloben in Ihrer Datei zu verwenden, damit diese Adressierungsmodi ( [msg]und [title]) die RIP-relative Adressierung anstelle der absoluten 32-Bit-Adresse verwenden.
Peter Cordes
5
Es sei denn , Sie rufen eine Funktion ist dies keineswegs trivial. (Und im Ernst, es gibt keinen wirklichen Unterschied in der Komplexität zwischen dem Aufrufen von printf und dem Aufrufen einer win32-API-Funktion.)
Selbst DOS int 21h ist eigentlich nur ein Funktionsaufruf, auch wenn es sich um eine andere API handelt.
Wenn Sie dies ohne Hilfe tun möchten, müssen Sie direkt mit Ihrer Videohardware sprechen und wahrscheinlich Bitmaps der Buchstaben von "Hello world" in einen Framebuffer schreiben. Selbst dann übersetzt die Grafikkarte diese Speicherwerte in VGA / DVI-Signale.
Beachten Sie, dass in ASM keines dieser Dinge bis hin zur Hardware interessanter ist als in C. Ein "Hallo Welt" -Programm läuft auf einen Funktionsaufruf hinaus. Eine schöne Sache bei ASM ist, dass Sie jedes gewünschte ABI ziemlich einfach verwenden können. Sie müssen nur wissen, was dieser ABI ist.
Dies ist ein ausgezeichneter Punkt - ASM und C basieren beide auf einer vom Betriebssystem bereitgestellten Funktion (_WriteFile in Windows). Wo ist also die Magie? Es befindet sich im Gerätetreibercode für die Grafikkarte.
Assad Ebrahim
2
Dies ist durchaus nebensächlich. Das Poster fragt ein Assembler-Programm, das "unter Windows" ausgeführt wird. Das bedeutet, dass Windows-Funktionen verwendet werden können (z. B. kernel32.dll), jedoch keine anderen Funktionen wie libc unter Cygwin. Zum lauten Schreien steht auf dem Plakat ausdrücklich keine C-Bibliothek.
Albert van der Horst
5
Die besten Beispiele sind solche mit fasm, da fasm keinen Linker verwendet, wodurch die Komplexität der Windows-Programmierung durch eine andere undurchsichtige Komplexitätsebene verborgen wird. Wenn Sie mit einem Programm zufrieden sind, das in ein GUI-Fenster schreibt, finden Sie ein Beispiel dafür im Beispielverzeichnis von fasm.
Wenn Sie ein Konsolenprogramm wünschen, können Sie auch Standard-In und Standard-Out umleiten, was ebenfalls möglich ist. Es gibt ein (helas höchst nicht triviales) Beispielprogramm, das keine GUI verwendet und streng mit der Konsole arbeitet, das ist fasm selbst. Dies kann auf das Wesentliche ausgedünnt werden. (Ich habe einen vierten Compiler geschrieben, der ein weiteres Nicht-GUI-Beispiel ist, aber auch nicht trivial).
Ein solches Programm verfügt über den folgenden Befehl, um einen ordnungsgemäßen ausführbaren Header zu generieren, der normalerweise von einem Linker ausgeführt wird.
FORMAT PE CONSOLE
Ein Abschnitt mit dem Namen '.idata' enthält eine Tabelle, mit deren Hilfe Windows beim Start Namen von Funktionen mit den Laufzeitadressen koppeln kann. Es enthält auch einen Verweis auf KERNEL.DLL, das Windows-Betriebssystem.
Das Tabellenformat wird von Windows vorgegeben und enthält Namen, die beim Starten des Programms in Systemdateien nachgeschlagen werden. FASM verbirgt einen Teil der Komplexität hinter dem Schlüsselwort rva. _ExitProcess @ 4 ist also ein fasm-Label und _exitProcess ist eine Zeichenfolge, die von Windows nachgeschlagen wird.
Ihr Programm befindet sich im Abschnitt '.text'. Wenn Sie diesen Abschnitt als lesbar, beschreibbar und ausführbar deklarieren, ist dies der einzige Abschnitt, den Sie hinzufügen müssen.
section '.text' code executable readable writable
Sie können alle Einrichtungen aufrufen, die Sie im Abschnitt .idata deklariert haben. Für ein Konsolenprogramm benötigen Sie _GetStdHandle, um die Dateideskriptoren für Standard-In und Standardout zu finden (unter Verwendung symbolischer Namen wie STD_INPUT_HANDLE, die fasm in der Include-Datei win32a.inc findet). Sobald Sie die Dateideskriptoren haben, können Sie WriteFile und ReadFile ausführen. Alle Funktionen sind in der Kernel32-Dokumentation beschrieben. Sie sind sich dessen wahrscheinlich bewusst, oder Sie würden die Assembler-Programmierung nicht ausprobieren.
Zusammenfassend: Es gibt eine Tabelle mit ASCI-Namen, die mit dem Windows-Betriebssystem gekoppelt sind. Während des Startvorgangs wird dies in eine Tabelle mit aufrufbaren Adressen umgewandelt, die Sie in Ihrem Programm verwenden.
FASM verwendet möglicherweise keinen Linker, muss jedoch eine PE-Datei zusammenstellen. Das bedeutet, dass es nicht nur Code zusammensetzt, sondern auch einen Job übernimmt, den normalerweise ein Linker ausführen würde, und als solche ist es meiner bescheidenen Meinung nach irreführend, die Abwesenheit eines Linkers als "versteckte Komplexität" zu bezeichnen, ganz im Gegenteil - Die Aufgabe eines Assemblers besteht darin, ein Programm zusammenzustellen, es jedoch dem Linker zu überlassen, das Programm in ein Programmabbild einzubetten, das von vielen Dingen abhängen kann. Daher finde ich die Trennung zwischen einem Linker und einem Assembler eine gute Sache, über die Sie offenbar nicht einig sind.
Amn
@amn Denk so darüber nach. Wenn Sie einen Linker verwenden, um das obige Programm zu erstellen, erhalten Sie dann mehr Einblick in die Funktionsweise des Programms oder woraus besteht es? Wenn ich mir die Fasm-Quelle anschaue, kenne ich die vollständige Struktur des Programms.
Albert van der Horst
Gutes Argument. Auf der anderen Seite hat die Trennung der Verknüpfung von allem anderen auch Vorteile. Normalerweise haben Sie Zugriff auf eine Objektdatei (was einen großen Beitrag dazu leistet, dass Sie unabhängig vom Format der Programmbilddatei auch die Struktur eines Programms überprüfen können). Sie können einen anderen Linker Ihrer Wahl mit verschiedenen Optionen aufrufen. Es geht um Wiederverwendbarkeit und Zusammensetzbarkeit. In diesem Sinne tut FASM alles, weil es "bequem" ist, diese Prinzipien zu brechen. Ich bin nicht grundsätzlich dagegen - ich sehe ihre Rechtfertigung dafür -, aber ich brauche es nicht.
Amn
Erhalten Sie Fehler für illegale isntruction in der obersten Zeile in fasm 64-Bit-Fenstern
bluejayke
3
Wenn Sie den Linker von NASM und Visual Studio (link.exe) mit dem Hello World-Beispiel von anderstornvig verwenden möchten, müssen Sie manuell eine Verknüpfung mit der C Runtime Libary herstellen, die die Funktion printf () enthält.
Antworten:
NASM-Beispiele .
Libc stdio aufrufen
printf
, implementierenint main(){ return printf(message); }
Dann renne
Es gibt auch den Leitfaden für ahnungslose Neulinge zu Hello World in Nasm ohne Verwendung einer C-Bibliothek. Dann würde der Code so aussehen.
16-Bit-Code mit MS-DOS-Systemaufrufen: Funktioniert in DOS-Emulatoren oder in 32-Bit-Windows mit NTVDM-Unterstützung . Kann unter 64-Bit-Windows nicht "direkt" (transparent) ausgeführt werden, da ein x86-64-Kernel den VM86-Modus nicht verwenden kann.
Bauen Sie dies in eine
.com
ausführbare Datei ein, damitcs:100h
alle Segmentregister gleich sind (winziges Speichermodell).Viel Glück.
quelle
Dieses Beispiel zeigt, wie Sie direkt zur Windows-API wechseln und keine Verknüpfung in der C-Standardbibliothek herstellen.
Zum Kompilieren benötigen Sie NASM und LINK.EXE (von Visual Studio Standard Edition).
quelle
gcc hello.obj
Dies sind Win32- und Win64-Beispiele mit Windows-API-Aufrufen. Sie sind eher für MASM als für NASM, aber sehen Sie sie sich an. Weitere Details finden Sie in diesem Artikel.
Dies verwendet MessageBox, anstatt auf stdout zu drucken.
Win32 MASM
Win64 MASM
Verwenden Sie dies für die ausführbare 32-Bit-Datei, um diese mithilfe von MASM zusammenzustellen und zu verknüpfen:
oder dies für eine ausführbare 64-Bit-Datei:
Warum muss x64 Windows vor a 28 Stunden Byte Stapelspeicher reservieren
call
? Das sind 32 Byte (0x20) Schattenraum, auch bekannt als Heimatraum, wie es die aufrufende Konvention vorschreibt. Und weitere 8 Bytes, um den Stapel um 16 neu auszurichten, da die Aufrufkonvention erfordert, dass RSP 16 Byte vor a ausgerichtet istcall
. (main
Der Anrufer von Our (im CRT-Startcode) hat dies getan. Die 8-Byte-Rücksprungadresse bedeutet, dass RSP beim Eintritt in eine Funktion 8 Byte von einer 16-Byte-Grenze entfernt ist.)Der Schattenraum kann von einer Funktion verwendet werden, um ihre Registerargumente neben den Stapelargumenten (falls vorhanden) abzulegen. A
system call
benötigt 30 Stunden (48 Bytes), um zusätzlich zu den zuvor erwähnten 4 Registern auch Platz für r10 und r11 zu reservieren. DLL-Aufrufe sind jedoch nur Funktionsaufrufe, selbst wenn siesyscall
Anweisungen umschließen .Unterhaltsame Tatsache: Nicht-Windows, dh die x86-64-System V-Aufrufkonvention (z. B. unter Linux) verwendet überhaupt keinen Schattenraum und verwendet bis zu 6 Ganzzahl- / Zeigerregister-Argumente und bis zu 8 FP-Argumente in XMM-Registern .
Mit der MASM-
invoke
Direktive (die die Aufrufkonvention kennt) können Sie ein ifdef verwenden, um eine Version davon zu erstellen, die als 32-Bit oder 64-Bit erstellt werden kann.Die Makrovariante ist für beide gleich, aber Sie werden das Zusammenbauen auf diese Weise nicht lernen. Sie lernen stattdessen Asm im C-Stil.
invoke
ist fürstdcall
oderfastcall
währendcinvoke
ist fürcdecl
oder variables Argumentfastcall
. Der Assembler weiß, welche er verwenden soll.Sie können die Ausgabe zerlegen, um zu sehen, wie
invoke
erweitert.quelle
title
Fehler auf, wenn ich ihn als Beschriftungsnamen verwende. Wenn ich jedoch etwas anderes als Markennamen verwendemytitle
, funktioniert alles einwandfrei.Flat Assembler benötigt keinen zusätzlichen Linker. Dies macht die Assembler-Programmierung ziemlich einfach. Es ist auch für Linux verfügbar.
Dies ist
hello.asm
aus den Fasm-Beispielen:Fasm erstellt eine ausführbare Datei:
Und das ist das Programm in IDA :
Sie können die drei Anrufe sehen:
GetCommandLine
,MessageBox
undExitProcess
.quelle
Um eine .exe mit NASM'compiler und dem Linker von Visual Studio zu erhalten, funktioniert dieser Code einwandfrei:
Wenn dieser Code zB auf "test64.asm" gespeichert ist, müssen Sie Folgendes kompilieren:
Erzeugt "test64.obj". Zum Verknüpfen über die Eingabeaufforderung:
wo path_to_link könnte C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC \ ist oder wo auch immer Ihr link.exe Programm in Ihrer Maschine, path_to_libs könnte C: \ Program Files (x86) \ Windows - Kits \ 8.1 \ Lib \ winv6.3 \ um \ x64 oder wo immer sich Ihre Bibliotheken befinden (in diesem Fall befinden sich sowohl kernel32.lib als auch user32.lib an derselben Stelle, andernfalls verwenden Sie eine Option für jeden Pfad, den Sie benötigen) und / largeaddressaware: Keine Option notwendig, um zu vermeiden, dass Linker sich zu lange über Adressen beschweren (in diesem Fall für user32.lib). Wenn hier der Linker von Visual über die Eingabeaufforderung aufgerufen wird, muss die Umgebung zuvor eingerichtet werden (einmal vcvarsall.bat ausführen und / oder MS C ++ 2010 und mspdb100.dll anzeigen)).
quelle
default rel
oben in Ihrer Datei zu verwenden, damit diese Adressierungsmodi ([msg]
und[title]
) die RIP-relative Adressierung anstelle der absoluten 32-Bit-Adresse verwenden.Es sei denn , Sie rufen eine Funktion ist dies keineswegs trivial. (Und im Ernst, es gibt keinen wirklichen Unterschied in der Komplexität zwischen dem Aufrufen von printf und dem Aufrufen einer win32-API-Funktion.)
Selbst DOS int 21h ist eigentlich nur ein Funktionsaufruf, auch wenn es sich um eine andere API handelt.
Wenn Sie dies ohne Hilfe tun möchten, müssen Sie direkt mit Ihrer Videohardware sprechen und wahrscheinlich Bitmaps der Buchstaben von "Hello world" in einen Framebuffer schreiben. Selbst dann übersetzt die Grafikkarte diese Speicherwerte in VGA / DVI-Signale.
Beachten Sie, dass in ASM keines dieser Dinge bis hin zur Hardware interessanter ist als in C. Ein "Hallo Welt" -Programm läuft auf einen Funktionsaufruf hinaus. Eine schöne Sache bei ASM ist, dass Sie jedes gewünschte ABI ziemlich einfach verwenden können. Sie müssen nur wissen, was dieser ABI ist.
quelle
Die besten Beispiele sind solche mit fasm, da fasm keinen Linker verwendet, wodurch die Komplexität der Windows-Programmierung durch eine andere undurchsichtige Komplexitätsebene verborgen wird. Wenn Sie mit einem Programm zufrieden sind, das in ein GUI-Fenster schreibt, finden Sie ein Beispiel dafür im Beispielverzeichnis von fasm.
Wenn Sie ein Konsolenprogramm wünschen, können Sie auch Standard-In und Standard-Out umleiten, was ebenfalls möglich ist. Es gibt ein (helas höchst nicht triviales) Beispielprogramm, das keine GUI verwendet und streng mit der Konsole arbeitet, das ist fasm selbst. Dies kann auf das Wesentliche ausgedünnt werden. (Ich habe einen vierten Compiler geschrieben, der ein weiteres Nicht-GUI-Beispiel ist, aber auch nicht trivial).
Ein solches Programm verfügt über den folgenden Befehl, um einen ordnungsgemäßen ausführbaren Header zu generieren, der normalerweise von einem Linker ausgeführt wird.
Ein Abschnitt mit dem Namen '.idata' enthält eine Tabelle, mit deren Hilfe Windows beim Start Namen von Funktionen mit den Laufzeitadressen koppeln kann. Es enthält auch einen Verweis auf KERNEL.DLL, das Windows-Betriebssystem.
Das Tabellenformat wird von Windows vorgegeben und enthält Namen, die beim Starten des Programms in Systemdateien nachgeschlagen werden. FASM verbirgt einen Teil der Komplexität hinter dem Schlüsselwort rva. _ExitProcess @ 4 ist also ein fasm-Label und _exitProcess ist eine Zeichenfolge, die von Windows nachgeschlagen wird.
Ihr Programm befindet sich im Abschnitt '.text'. Wenn Sie diesen Abschnitt als lesbar, beschreibbar und ausführbar deklarieren, ist dies der einzige Abschnitt, den Sie hinzufügen müssen.
Sie können alle Einrichtungen aufrufen, die Sie im Abschnitt .idata deklariert haben. Für ein Konsolenprogramm benötigen Sie _GetStdHandle, um die Dateideskriptoren für Standard-In und Standardout zu finden (unter Verwendung symbolischer Namen wie STD_INPUT_HANDLE, die fasm in der Include-Datei win32a.inc findet). Sobald Sie die Dateideskriptoren haben, können Sie WriteFile und ReadFile ausführen. Alle Funktionen sind in der Kernel32-Dokumentation beschrieben. Sie sind sich dessen wahrscheinlich bewusst, oder Sie würden die Assembler-Programmierung nicht ausprobieren.
Zusammenfassend: Es gibt eine Tabelle mit ASCI-Namen, die mit dem Windows-Betriebssystem gekoppelt sind. Während des Startvorgangs wird dies in eine Tabelle mit aufrufbaren Adressen umgewandelt, die Sie in Ihrem Programm verwenden.
quelle
Wenn Sie den Linker von NASM und Visual Studio (link.exe) mit dem Hello World-Beispiel von anderstornvig verwenden möchten, müssen Sie manuell eine Verknüpfung mit der C Runtime Libary herstellen, die die Funktion printf () enthält.
Hoffe das hilft jemandem.
quelle