আমি উইন্ডোজের অধীনে সমাবেশে বেসিক কিছু লিখতে চেয়েছিলাম, আমি এনএএসএম ব্যবহার করছি, তবে আমি কিছুই কাজ করতে পারি না।
উইন্ডোজে সি ফাংশনগুলির সাহায্য ছাড়াই হ্যালো ওয়ার্ল্ড কীভাবে লিখবেন এবং সংকলন করবেন?
আমি উইন্ডোজের অধীনে সমাবেশে বেসিক কিছু লিখতে চেয়েছিলাম, আমি এনএএসএম ব্যবহার করছি, তবে আমি কিছুই কাজ করতে পারি না।
উইন্ডোজে সি ফাংশনগুলির সাহায্য ছাড়াই হ্যালো ওয়ার্ল্ড কীভাবে লিখবেন এবং সংকলন করবেন?
উত্তর:
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
এর রয়েছে Nasm মধ্যে হ্যালো ওয়ার্ল্ড থেকে clueless newbies গাইড একটি C লাইব্রেরি ব্যবহার না করে। তারপরে কোডটি এর মতো দেখাবে।
এমএস-ডস সিস্টেম কলগুলির সাথে 16-বিট কোড: ডস এমুলেটরগুলিতে বা এনটিভিডিএম সমর্থন সহ 32-বিট উইন্ডোতে কাজ করে । যে কোনও -৪-বিট উইন্ডোজের অধীনে "সরাসরি" (স্বচ্ছভাবে) চালানো যায় না কারণ একটি x86-64 কার্নেল ভিএম 86 মোড ব্যবহার করতে পারে না।
org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h
msg db 'Hello, World!',0Dh,0Ah,'$'
.com
এটিকে একটি এক্সিকিউটেবল হিসাবে তৈরি করুন যাতে এটি cs:100h
একে অপরের সমান (ছোট মেমরির মডেল) সমান সমস্ত বিভাগ রেজিস্টারগুলিতে লোড হবে ।
শুভকামনা।
এই উদাহরণটি দেখায় যে কীভাবে সরাসরি উইন্ডোজ এপিআইতে যেতে হয় এবং সি স্ট্যান্ডার্ড লাইব্রেরিতে লিঙ্ক না হয়।
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 (ভিজ্যুয়াল স্টুডিও স্ট্যান্ডার্ড সংস্করণ থেকে) প্রয়োজন
nasm -fwin32 hello.asm লিঙ্ক / সাবসিস্টেম: কনসোল / নোডফলিটিব / এন্ট্রি: প্রধান হ্যালো.ওবজ
gcc hello.obj
এগুলি উইন্ডোজ এপিআই কলগুলি ব্যবহার করে উইন 32 এবং উইন 64 উদাহরণ। তারা এনএএসএমের চেয়ে এমএএসএমের জন্য, তবে তাদের একবার দেখুন। আপনি এই নিবন্ধে আরও বিশদ জানতে পারেন ।
এটি স্টডআউটে মুদ্রণের পরিবর্তে মেসেজবক্স ব্যবহার করে।
;---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
এমএএসএম ব্যবহার করে এগুলিকে একত্রিত করতে এবং লিঙ্ক করতে, 32-বিট এক্সিকিউটেবলের জন্য এটি ব্যবহার করুন:
ml.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main
বা এটি -৪-বিট এক্সিকিউটেবলের জন্য:
ml64.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main
X64 উইন্ডোজকে কেন একটি এর আগে স্ট্যাক স্পেসের 28 ঘন্টা বাইট সংরক্ষণ করতে হবে call
? কলিং কনভেনশন দ্বারা প্রয়োজনীয় এটি শ্যাডো স্পেস ওরফে হোম স্পেসের 32 বাইট (0x20) আর আরেকটি 8 বাইট 16 দ্বারা স্ট্যাকের পুনরায় সারিবদ্ধ, কারণ কলিং সম্মেলন আরএসপি 16-বাইট প্রান্তিককৃত হতে প্রয়োজন সামনে একটি call
। (আমাদের main
কলার (সিআরটি স্টার্টআপ কোডে) তা করেছে 8 8-বাইট রিটার্ন ঠিকানাটির অর্থ আরএসপি কোনও ফাংশনে প্রবেশের সময় 16 বাইটের সীমানা থেকে 8 বাইট দূরে))
শ্যাডো স্পেসটি কোনও ফাংশন দ্বারা তার রেজিস্টার আরগগুলি ডাম্প করার জন্য ব্যবহার করতে পারে যেখানে কোনও স্ট্যাক আরগস (যদি থাকে) থাকে। A system call
এর পূর্বে উল্লিখিত 4 টি রেজিস্টার ছাড়াও r10 এবং r11 এর জন্য স্থান সংরক্ষণ করার জন্য 30 ঘন্টা (48 বাইট) প্রয়োজন। তবে ডিএলএল কলগুলি কেবল ফাংশন কল, যদিও তারা syscall
নির্দেশাবলীর আশেপাশে মোড়ক হয় ।
মজার বিষয়: অ উইন্ডোজ, অর্থাত্ x86-64 সিস্টেম ভী আহ্বান কনভেনশন (লিনাক্সের উপর যেমন) এ সব ছায়া স্থান ব্যবহার করে না, এবং 6 পূর্ণসংখ্যা / পয়েন্টার রেজিস্টার args ব্যবহার করে, এবং XMM রেজিস্টার 8 FP args পর্যন্ত ।
এমএএসএমের invoke
নির্দেশিকা (যা কলিং কনভেনশনটি জানে) ব্যবহার করে আপনি এর একটি সংস্করণ তৈরি করতে একটি ifdef ব্যবহার করতে পারেন যা 32-বিট বা 64-বিট হিসাবে নির্মিত যেতে পারে।
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
ম্যাক্রো বৈকল্পিক উভয়ের জন্য একই, তবে আপনি এইভাবে সমাবেশ শিখবেন না। আপনি পরিবর্তে সি স্টাইলের asm শিখবেন। পরিবর্তনশীল আর্গুমেন্টের invoke
জন্য হয় stdcall
বা fastcall
যখন cinvoke
হয় । কোনটি ব্যবহার করতে হবে তা এসেমব্লার জানে।cdecl
fastcall
কীভাবে invoke
প্রসারিত হয়েছে তা দেখতে আপনি আউটপুটকে আলাদা করতে পারেন ।
title
লেবেলের নাম হিসাবে ব্যবহার করি তখন আমি ত্রুটিগুলিতে চলে যাই। তবে আমি যখন লেবেল নামের মতো অন্য কিছু ব্যবহার করি তখন mytitle
সবকিছু ঠিকঠাক হয়।
ফ্ল্যাট অ্যাসেমব্লারের অতিরিক্ত লিঙ্কারের প্রয়োজন নেই। এটি এসেম্বলারের প্রোগ্রামিংকে বেশ সহজ করে তোলে। এটি লিনাক্সের জন্যও উপলব্ধ।
এটি hello.asm
ফ্যাসমের উদাহরণ থেকে:
include 'win32ax.inc'
.code
start:
invoke MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
invoke ExitProcess,0
.end start
ফ্যাসম একটি এক্সিকিউটেবল তৈরি করে:
> ফাস্ট হ্যালো.আসএম ফ্ল্যাট অ্যাসেমব্লার সংস্করণ 1.70.03 (1048575 কিলোবাইট মেমরি) 4 পাস, 1536 বাইট।
এবং এই আইডিএ প্রোগ্রাম :
আপনি তিনটি কল দেখতে পারেন: GetCommandLine
, MessageBox
এবং ExitProcess
।
NASM'compiler এবং ভিজ্যুয়াল স্টুডিওর লিঙ্কারের সাথে একটি .exe পেতে এই কোডটি দুর্দান্ত কাজ করে:
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 সি হতে পারে : \ প্রোগ্রাম ফাইলগুলি (x86) \ মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও 10.0 \ ভিসি \ বিন বা যেখানেই আপনার মেশিনে আপনার লিঙ্ক.এক্সপি প্রোগ্রাম থাকতে পারে , path_to_libs সি হতে পারে : \ প্রোগ্রাম ফাইল (x86) \ উইন্ডোজ কিটস \ 8.1 \ লিব \ winv6.3 \ um \ x64 বা আপনার গ্রন্থাগারগুলি যেখানেই রয়েছে (এক্ষেত্রে কার্নেল 32.lib এবং ব্যবহারকারী 32.lib উভয়ই একই জায়গায় রয়েছে, অন্যথায় আপনার প্রয়োজন প্রতিটি পাথের জন্য একটি বিকল্প ব্যবহার করুন) এবং / ল্যাড্যাড্রেসারওয়্যার: কোনও বিকল্প নেই লম্বা ঠিকানাগুলির বিষয়ে লিঙ্কারের অভিযোগ এড়াতে প্রয়োজনীয় (এই ক্ষেত্রে ব্যবহারকারী 32.লিবের জন্য)। এছাড়াও, এখানে যেমন করা হয়েছে, ভিজ্যুয়ালের লিঙ্কারটি যদি কমান্ড প্রম্পট থেকে আহ্বান করা হয়, পরিবেশটি পূর্বে সেটআপ করা প্রয়োজন (একবার vcvarsall.bat চালান এবং / অথবা এমএস সি ++ 2010 এবং mspdb100.dll দেখুন)।
default rel
আপনার ফাইলের শীর্ষে ব্যবহার করার পরামর্শ দিচ্ছি যাতে সেই ঠিকানাগুলি ( [msg]
এবং [title]
) 32-বিট পরম পরিবর্তে আরআইপি-আপেক্ষিক ঠিকানা ব্যবহার করে।
আপনি কিছু ফাংশন কল না করলে এটি মোটেই তুচ্ছ নয়। (এবং, গুরুত্বের সাথে, প্রিন্টএফ কল করা এবং উইন 32 এপিআই ফাংশন কল করার মধ্যে জটিলতার কোনও বাস্তব পার্থক্য নেই))
এমনকি ডস ইন্ট ২১ এইচটি সত্যিই কেবল একটি ফাংশন কল, এমনকি এটির আলাদা একটি এপিআই।
আপনি যদি সহায়তা ছাড়াই এটি করতে চান তবে আপনার ভিডিও হার্ডওয়্যারের সাথে সরাসরি কথা বলার দরকার রয়েছে, সম্ভবত "হ্যালো ওয়ার্ল্ড" এর অক্ষরগুলির বিটম্যাপগুলি ফ্রেমবফারে লিখতে হবে। তারপরেও ভিডিও কার্ড সেই মেমরির মানগুলিকে ভিজিএ / ডিভিআই সংকেতগুলিতে অনুবাদ করার কাজ করছে।
মনে রাখবেন যে, সত্যিই, হার্ডওয়ারের পুরো পথে এই স্টাফগুলির কোনওটি সি এর চেয়ে এএসএমের চেয়ে আকর্ষণীয় নয় " এএসএম সম্পর্কে একটি দুর্দান্ত জিনিস হ'ল আপনি যে কোনও এবিআই ব্যবহার করতে চান মোটামুটি সহজ; আপনাকে কেবল এবিআই কী তা জানতে হবে।
ফাস্ট উদাহরণগুলি হ'ল সর্বোত্তম উদাহরণগুলি, কারণ ফাস্টাম কোনও লিঙ্কার ব্যবহার করে না, যা উইন্ডোজ প্রোগ্রামিংয়ের জটিলতাটিকে অন্য একটি অস্বচ্ছ স্তর দ্বারা আড়াল করে। আপনি যদি এমন কোনও প্রোগ্রামে সন্তুষ্ট হন যা একটি গুই উইন্ডোতে লেখেন, তবে ফাস্টমের উদাহরণ ডিরেক্টরিতে এটির জন্য একটি উদাহরণ রয়েছে।
যদি আপনি কোনও কনসোল প্রোগ্রাম চান তবে এটি স্ট্যান্ডার্ড ইন এবং স্ট্যান্ডার্ডকে পুনর্নির্দেশের অনুমতি দেয় যা এটিও সম্ভব। এখানে একটি (হেলাস অত্যন্ত অ-তুচ্ছ) উদাহরণ রয়েছে যা একটি গুই ব্যবহার করে না এবং কনসোলটি নিয়ে কঠোরভাবে কাজ করে, এটি নিজেই দ্রুত। এটি প্রয়োজনীয় থেকে পাতলা করা যেতে পারে। (আমি একটি সামনের কম্পাইলার লিখেছি যা অন্য একটি নন-গুই উদাহরণ, তবে এটি অ-তুচ্ছও)।
এই জাতীয় প্রোগ্রামের 32-বিট এক্সিকিউটেবলের জন্য যথাযথ শিরোনাম উত্পন্ন করার জন্য নিম্নলিখিত কমান্ডটি থাকে যা সাধারণত কোনও লিঙ্কার দ্বারা সম্পন্ন হয়।
FORMAT PE CONSOLE
'.Idata' নামক একটি বিভাগে একটি টেবিল রয়েছে যা রানটাইম অ্যাড্রেসের ফাংশনের দু'জনের নামের শুরুতে উইন্ডোগুলিকে সহায়তা করে। এটিতে কার্নেল.ডিএলএল-এর একটি উল্লেখ রয়েছে যা উইন্ডোজ অপারেটিং সিস্টেম।
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
টেবিল বিন্যাসটি উইন্ডোজ দ্বারা চাপিয়ে দেওয়া হয় এবং প্রোগ্রাম শুরু হওয়ার পরে সিস্টেম ফাইলগুলিতে সন্ধান করা নামগুলি অন্তর্ভুক্ত থাকে। FASM আরভিএ কীওয়ার্ডের পিছনে কিছু জটিলতা আড়াল করে। সুতরাং _ExitProcess @ 4 একটি দ্রুততম লেবেল এবং _exitProcess একটি স্ট্রিং যা উইন্ডোজ দ্বারা দেখা হয়।
আপনার প্রোগ্রামটি '.text' বিভাগে রয়েছে। আপনি যদি সেই বিভাগটি পাঠযোগ্যযোগ্য এবং কার্যকরযোগ্য হিসাবে ঘোষণা করেন তবে এটি কেবলমাত্র আপনাকে যুক্ত করতে হবে।
section '.text' code executable readable writable
আপনি .আইডাটা বিভাগে আপনি যে সমস্ত সুবিধা ঘোষণা করেছেন তা কল করতে পারেন। কোন কনসোল প্রোগ্রামের জন্য আপনার স্ট্যান্ডার্ড এবং স্ট্যান্ডার্ড আউট (এসটিডিএনপিপিউ এসএইচডিএল এর মতো প্রতীকী নাম ব্যবহার করে যা উইন 32 এ.সিঙ্ক ফাইলটি অন্তর্ভুক্ত করে) এর জন্য প্রতীকী নাম ব্যবহার করে আপনাকে _গেটস্পটহ্যান্ডল দরকার। একবার ফাইল বর্ণনাকারী হয়ে গেলে আপনি WritFile এবং ReadFile করতে পারেন। সমস্ত ফাংশন কার্নেল 32 ডকুমেন্টেশনে বর্ণিত হয়েছে। আপনি সম্ভবত এটি সম্পর্কে অবগত আছেন বা আপনি এসেম্বলার প্রোগ্রামিংয়ের চেষ্টা করবেন না।
সংক্ষেপে: উইন্ডোজ ওএসে দু'একটি নাম সহ একটি টেবিল রয়েছে। প্রারম্ভকালীন সময় এটি কলযোগ্য ঠিকানার টেবিলে রূপান্তরিত হয়, যা আপনি আপনার প্রোগ্রামে ব্যবহার করেন।
যদি আপনি অ্যান্ডার্সটর্নভিগের হ্যালো ওয়ার্ল্ড উদাহরণের সাথে এনএএসএম এবং ভিজ্যুয়াল স্টুডিওর লিঙ্কার (link.exe) ব্যবহার করতে চান তবে আপনাকে ম্যানুয়ালি সি রানটাইম লিবারির সাথে লিঙ্ক করতে হবে যাতে মুদ্রণ () ফাংশন রয়েছে।
nasm -fwin32 helloworld.asm
link.exe helloworld.obj libcmt.lib
আশা করি এটি কাউকে সাহায্য করবে।