Как написать hello world в ассемблере под Windows?
Я хотел написать что-то основное в сборке под Windows, я использую NASM, но я ничего не могу заставить работать.
Как написать и скомпилировать hello world без помощи функций C в Windows?
8 ответов
вызов libc stdio printf
, осуществляет int main(){ return printf(message); }
; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is 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
затем запустите
nasm -fwin32 helloworld.asm
gcc helloworld.obj
a
там же невежественные новички руководство Hello World в Nasm без использования библиотеки C. Тогда код будет выглядеть так.
16-битный код с системными вызовами MS-DOS: работает в эмуляторах DOS или в 32-битных окнах с поддержкой NTVDM. Невозможно запустить " напрямую" (прозрачно) под любой 64-разрядной Windows, потому что ядро x86-64 не может использовать режим vm86.
org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h
msg db 'Hello, World!',0Dh,0Ah,'$'
построить в .com
исполняемый файл, поэтому он будет загружен на cs:100h
со всеми регистрами сегмента, равными друг другу (крошечная модель памяти).
удачи.
в этом примере показано, как перейти непосредственно к API Windows и не связываться в стандартной библиотеке C.
global _main
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
push -11
call _GetStdHandle@4
mov ebx, eax
; WriteFile( hstdOut, message, length(message), &bytes, 0);
push 0
lea eax, [ebp-4]
push eax
push (message_end - message)
push message
push ebx
call _WriteFile@20
; ExitProcess(0)
push 0
call _ExitProcess@4
; never here
hlt
message:
db 'Hello, World', 10
message_end:
для компиляции вам понадобится NASM и LINK.EXE (из Visual studio Standard Edition)
nasm -fwin32 hello.asm link /subsystem:console /nodefaultlib /entry:main hello.obj
это примеры Win32 и Win64 с использованием вызовов Windows API. Они предназначены для MASM, а не NASM, но посмотрите на них. Вы можете найти более подробную информацию в этой статьи.
;---ASM Hello World Win32 MessageBox
.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 ExitProcess
End Main
;---ASM Hello World Win64 MessageBox
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 MessageBoxA
add rsp, 28h
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
main endp
End
чтобы собрать и связать их с помощью MASM, используйте это для 32-разрядного исполняемого файла:
ml.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main
или это для 64-битного исполняемого файла:
ml64.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main
Плоский Ассемблер не нужен дополнительный компоновщик. Это делает программирование ассемблера довольно простым. Он также доступен для Linux.
это hello.asm
из примеров Fasm:
include 'win32ax.inc'
.code
start:
invoke MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
invoke ExitProcess,0
.end start
Fasm создает исполняемый файл:
>fasm hello.asm flat assembler version 1.70.03 (1048575 kilobytes memory) 4 passes, 1536 bytes.
и это программа, в Мар:
вы можете увидеть три звонка: GetCommandLine
, MessageBox
и ExitProcess
.
получить .exe с NASM'Compiler и компоновщиком Visual Studio этот код отлично работает:
global WinMain
extern ExitProcess ; external functions in system libraries
extern MessageBoxA
section .data
title: db 'Win64', 0
msg: db 'Hello world!', 0
section .text
WinMain:
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 MessageBoxA
add rsp, 28h
mov ecx,eax
call ExitProcess
hlt ; never here
Если этот код сохранен, например, на " test64.asm", затем скомпилировать:
nasm -f win64 test64.asm
производит "test64.параметр obj" Затем перейти по ссылке из командной строки:
path_to_link\link.exe test64.obj /subsystem:windows /entry:WinMain /libpath:path_to_libs /nodefaultlib kernel32.lib user32.lib /largeaddressaware:no
здесь path_to_link может быть C:\Program файлы (x86)\Microsoft Visual Studio 10.0\VC\bin или где ваша ссылка.exe программы на вашем компьютере, path_to_libs может быть C:\Program файлы (x86)\Windows Kits\8.1\Lib\winv6.3 \ um\x64 или где находятся ваши библиотеки (в этом случае оба kernel32.lib и библиотека user32.lib находятся на одном месте, в противном случае используйте один вариант для каждого пути, который вам нужен) и /largeaddressaware:нет опция необходима, чтобы избежать жалоб компоновщика на адреса long (для user32.lib в данном случае). Кроме того, как это делается здесь, если компоновщик Visual вызывается из командной строки, необходимо настроить среда ранее (запустите один раз vcvarsall.bat and/or see в MS c++ 2010 и mspdb100.dll файлы).
Если вы не позвоните некоторые функция это совсем не тривиально. (И, серьезно, нет никакой реальной разницы в сложности между вызовом printf и вызовом функции win32 api.)
даже DOS int 21h-это просто вызов функции, даже если это другой API.
Если вы хотите сделать это без помощи, вам нужно напрямую поговорить с вашим видеооборудованием, вероятно, написав растровые изображения букв "Hello world" в фреймбуфер. Даже тогда видеокарта выполнение работы по переводу этих значений памяти в сигналы VGA/DVI.
обратите внимание, что, действительно, ни один из этих вещей вплоть до аппаратного обеспечения не более интересен в ASM, чем в C. программа "hello world" сводится к вызову функции. Одна хорошая вещь в ASM заключается в том, что вы можете использовать любой ABI, который хотите, довольно легко; вам просто нужно знать, что такое ABI.
Если вы хотите использовать компоновщик NASM и Visual Studio (ссылка.exe) с примером Hello World от anderstornvig вам придется вручную связать с библиотекой времени выполнения C, содержащей функцию printf ().
nasm -fwin32 helloworld.asm
link.exe helloworld.obj libcmt.lib
надеюсь, это кому-то поможет.
лучшими примерами являются fasm, потому что fasm не использует компоновщик, который скрывает сложность программирования windows другим непрозрачным слоем сложности. Если вы довольны программой, которая записывает в окно gui, то есть пример для этого в каталоге примера fasm.
Если вы хотите консольную программу, которая позволяет перенаправление standard in и standard out, что также возможно. Существует (helas очень нетривиальная) примерная программа, Доступная, что не использует gui и работает строго с консолью, то есть с самим fasm. Это может быть сведено к основам. (Я написал четвертый компилятор, который является еще одним примером без gui, но он также нетривиален).
такая программа имеет следующую команду для создания надлежащего исполняемого заголовка, обычно выполняемого компоновщиком.
FORMAT PE CONSOLE
раздел под названием '.idata ' содержит таблицу, которая помогает windows во время запуска связывать имена функций со временем выполнения адреса. Он также содержит ссылку на KERNEL.DLL, которая является операционной системой Windows.
section '.idata' import data readable writeable
dd 0,0,0,rva kernel_name,rva kernel_table
dd 0,0,0,0,0
kernel_table:
_ExitProcess@4 DD rva _ExitProcess
CreateFile DD rva _CreateFileA
...
...
_GetStdHandle@4 DD rva _GetStdHandle
DD 0
формат таблицы накладывается windows и содержит имена, которые просматриваются в системных файлах при запуске программы. FASM скрывает некоторые из сложность за ключевым словом rva. Таким образом, _ExitProcess@4-это метка fasm, а _exitProcess-строка, которая просматривается Windows.
программа находится в разделе '.текст". Если вы объявите этот раздел доступным для чтения и записи, исполняемый файл, это единственный раздел, который вам нужно добавить.
section '.text' code executable readable writable
вы можете вызвать все объекты, которые вы объявили в.секции idata по. Для консольной программы вам нужно _GetStdHandle найти его filedescriptors для standard in и standardout (используя символические имена, такие как STD_INPUT_HANDLE, который fasm находит в файле include win32a.inc). После того, как у вас есть файловые дескрипторы, вы можете сделать WriteFile и ReadFile. Все функции описаны в документации kernel32. Вы, вероятно, знаете или вы не стали бы пытаться программировать ассемблер.
в резюме: есть таблица с именами asci, которые соединяются с ОС windows. Во время запуска это преобразуется в таблицу вызываемых адресов, которую вы используете в своей программе.