Є миті
коли є враження, що opensource
чи вільне програмне
забезпечення в ОС Windows це
костиль над костилями, його роблять
так, аби він працював, аби працював.
Часто доводиться бачити приклад
компіляції під вільні ОС, а в Windows
все навпаки. Для прикладу
його компіляція і лінкування програми
в nasm, про
сам компілятор nasm ви
можете почитати в вікіпедії, про його
плюси та мінуси, історію розвитку:
Суть
питання в чому, після завантаження nasm
в Windows у
вас є лише компілятор, а
потім об'єктний файл потрібно компонувати ( лінкувати ) в формат ехе. Але просто зробити так:
$ nasm -f
win32 -o hello.exe hello.asm
Не вийде,
все одно nasm створить лиш об'єктний файл, в даному випадку ми
створили лиш його не розширенням *.obj,
a exe. Іншими словами, ми написали
наступне:
$ nasm -f
win32 -o hello.obj hello.asm
Є декілька
варіантів компіляції і компоновані файлів
в Windows:
1.
використати Alink
2.
MinGW ( GCC для
Windows )
3.
Binutils з використанням
ld ( для
зручності я використовую Cygwin
)
Завантажувати
файл alink.zip
Код має
виглядати так:
;Compilation program test
;nasm -fobj test.asm
;alink -oPE test.obj
// писати так як є без пробілів, бо буде
помилка при збірці
import MessageBoxA
user32.dll ;Include the dll user32.dll
extern MessageBoxA
; Now calling external symbol without underscore....
import ExitProcess
kernel32.dll
extern ExitProcess
section .data
msgme db "Це тест
програми на компановщику ALINk!",0
;Text
section .text use32
CLASS=CODE ;"use32 CLASS=CODE for telling the other
linker(Such as alink.exe) that program for 32bit
..start:
; ..start (not _start)
for other linker for start of the code
push dword 0x00
; MB_OK
mov
esi,msgme ;esi="[Text]"
push esi
; is now top of the stack, second paramaters title
push dword msgme
; Text
push dword 0
;Reserve
call [MessageBoxA]
;Call the Function MessageBoxA
push dword 0x00
call [ExitProcess]
Результат:
Так,
саме так повинен виглядати код для
компановщика alink. Замість
_start, ..start, також
вказуємо в області секції use32 CLASS=CODE,
вказати
компановщику, що це код для 32 бітної
системи. Також для інших секцій вказується
подібним прикладом:
SECTION DATA
USE32 CLASS=DATA
SECTION BSS USE32 CLASS=DATA
SECTION CODE USE32 CLASS=CODE
SECTION BSS USE32 CLASS=DATA
SECTION CODE USE32 CLASS=CODE
Також
можна писати section .text use32, покажемо
приклад, але вже для консольного варіанту
з API WriteConsole:
; Compilation & link
; nasm -f obj test.asm
; alink -oPE test2.obj
-subsys con
extern GetStdHandle
import GetStdHandle
kernel32.dll
extern WriteConsoleA
import WriteConsoleA
kernel32.dll
extern ExitProcess
import ExitProcess
kernel32.dll
section .data USE32
strich: db 'this is text
console!!!', 0xA
LenStich: equ $-strich
section .text USE32
..start:
push dword -11 ; -11
вивід на консоль
call [GetStdHandle] ;
результат буде в регістрі eax
push dword 0
push dword 0
push dword LenStich
push strich
push eax
call [WriteConsoleA]
push dword 0
call [ExitProcess]
Результат:
2.
З alink коротко розібрались,
тому переходимо до компановки за
допомогою GCC, слід зауважити,
що цей метод застосовують коли
використовують саме функції С, при цьому
краще використовувати Cygwin,
там все налаштовано, а якщо просто
ставити MinGW то можуть бути
помилки
; nasm
-fwin32 hello.asm
;
gcc hello.obj -o hello.exe
;
file name hello.asm compilation & linking obj
global _main
extern
_printf
section .data
fmtStr:
db 'Linker gcc hello.obj -o hello.exe test',
0xA, 0
section .text
_main:
sub
esp, 4 ; Allocate space on the stack for one 4 byte
parameter
lea
eax, [fmtStr]
mov
[esp], eax ; Arg1: pointer to format string
call
_printf ; Call printf(3):
add
esp, 4 ; Pop stack once
ret
; код взятий з сайту wikibooks
Результат:
3. Розглянемо
nasm + виклик win32 функцій
; Compilation & linker
; nasm -fwin32 file.asm
; ld -e _start file.obj -lkernel32 -o file.exe
global _start
extern _GetStdHandle@4
extern _WriteConsoleA@20
extern _ExitProcess@4
section .data
str: db 'hello, world',0xA
strLen: equ $-str
section .bss
numCharsWritten: resb 1
section .text
_start:
push dword 0 ; Arg5: Unused so just use zero
push numCharsWritten ; Arg4: push pointer to numCharsWritten
push dword strLen ; Arg3: push length of output string
push str ; Arg2: push pointer to output string
push eax ; Arg1: push handle returned from _GetStdHandle
call _WriteConsoleA@20
push dword 0 ; Arg1: push exit code
call _ExitProcess@4
; код взятий з сайту wikibooks
Результат
тексту програми буде такий самий , як і
в попередній. З особливостей,
тут ми вказали nasm що буде
вже проміжний файл win32 obj, -e параметром
вказали точку входу в програму, це в
нашому випадку _start, -l підключили
бібліотеку, всі win32 функції
відносяться до складу kernel32.dll, тому
пишемо -lkernel32.
Як бачимо
все залежить від від ОС, компановщика.
Вдалого вам лінкування.
Немає коментарів:
Дописати коментар