Как написать 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 и ссылка.EXE (от Visual studio Standard Edition)
nasm -fwin32 hello.asm link /subsystem:console /nodefaultlib /entry:main hello.obj
это примеры Win32 и Win64 с использованием вызовов API Windows. Они предназначены для 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:нет - это необходимо, чтобы избежать компоновщика жаловаться адресов длинные (библиотека user32.lib в данном случае). Кроме того, как это делается здесь, если компоновщик Visual вызывается из командной строки, необходимо настроить среда ранее (запустите один раз vcvarsall.летучая мышь и / или видеть 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.
Если вы хотите консольную программу, которая позволяет перенаправлять стандарт и стандарт, что тоже возможно. Существует (helas очень нетривиальный) пример программы, которая доступна не использует графический интерфейс, а работает строго с консолью, то есть сам fasm. Это можно прореживать до самых основ. (Я написал четвертый компилятор, который является еще одним примером без gui, но он также нетривиален).
такая программа имеет следующую команду для создания правильного исполняемого заголовка, обычно выполняемого компоновщиком.
FORMAT PE CONSOLE
раздел под названием '.idata ' содержит таблицу, которая помогает windows во время запуска связывать имена функций со средами выполнения адреса. Он также содержит ссылку на ядро.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 скрывает некоторые из сложности позади рва сайта. Таким образом, _ExitProcess@4-это метка fasm, а _exitProcess-это строка, которая просматривается Windows.
программа находится в разделе '.текст'. Если вы объявите этот раздел читаемым для записи и исполняемый файл, это единственный раздел, который вам нужно добавить.
section '.text' code executable readable writable
вы можете назвать все объекты, которые вы объявили в .секции idata по. Для консольной программы вам нужно _GetStdHandle, чтобы найти его filedescriptors для standard in и standardout (используя символические имена, такие как STD_INPUT_HANDLE, которые fasm находит в файле включения win32a.inc). После того, как у вас есть дескрипторы файлов, вы можете сделать WriteFile и ReadFile. Все функции описаны в документации kernel32. Вы, наверное, в курсе или вы не будете пытаться программировать ассемблер.
в резюме: есть таблица с именами asci, которые соединяются с ОС windows. Во время запуска это преобразуется в таблицу вызываемых адресов, которые вы используете в своей программе.