#assembly #x86 #mingw #nasm #ld
# #сборка #x86 #mingw #nasm #ld
Вопрос:
Я начинаю изучать сборку x86 в Windows. Я изучаю 32-разрядную сборку x86. Я использую nasm
и ld
для компиляции своих программ. Я использую mingw32-make
makefile в качестве моей системы сборки. Я предполагаю ld
, что оно включено в MinGW, но я не уверен в этом. Все, что я знаю, это то, что оно уже было на моем компьютере.
Я хотел скомпилировать очень простую программу, чтобы убедиться, что все работает, и, конечно, это не так. При запуске моего исполняемого файла появилось гигантское синее окно с надписью «Это приложение не может быть запущено на вашем ПК», и после закрытия уведомления слова Access is denied
были напечатаны на моем терминале.
Это моя программа:
global _main
_main:
mov eax, 1
ret
И это мой makefile:
main: learn.asm
nasm -f win32 learn.asm -o learn.o
ld learn.o -o learn.exe
Может кто-нибудь помочь мне исправить это?
Комментарии:
1. Вы уверены, что это не просто сбой, как и должно быть? Вам необходимо завершить работу программы. В Windows, я полагаю, вы можете просто
ret
.2. Не могли бы вы предоставить код в качестве ответа?
3. Просто вставьте
ret
aftermov eax, 1
.4. @Jester не работает: (
5. Есть ли в вашей среде
file
команда? Что он скажет, если вы запуститеfile learn.exe
?
Ответ №1:
Первоначально в вашем вопросе задавался вопрос об использовании _start
в качестве точки входа. Способ, которым вы связывали, не включал среду выполнения C.
В некоторых версиях Windows вы можете получить ошибку This app cant run on your pc
при соединении с MinGW LD, если .rdata
при некоторых обстоятельствах нет раздела (данные только для чтения). Одним из обстоятельств является исполняемый файл с .idata
разделом (каталог импорта), на который не ссылается заголовок, и который не содержит .rdata
раздела. Похоже, это тот случай, когда компоновщик MinGW LD создает исполняемый файл из вашего кода, когда не используется среда выполнения C. Чтобы устранить проблему, добавьте .rdata
раздел с хотя бы одним байтом данных. Это должно сработать:
global _start
section .rdata
db 0
section .text
_start:
mov eax, 1
ret
Вам также необходимо разместить свой код в этом .text
разделе, иначе вы можете столкнуться с другими проблемами. Затем вы можете собрать и связать с:
nasm -fwin32 learn.asm -o learn.obj
ld -o learn.obj -o learn.exe
Если вы хотите использовать _main
и намерены использовать среду выполнения C, то вам не нужно создавать .rdata
раздел, однако вы могли бы собрать и связать с:
nasm -fwin32 learn.asm -o learn.obj
gcc -m32 learn.obj -o learn.exe
Моя рекомендация по связыванию
В качестве альтернативы вы можете использовать компоновщик, отличный от LD. GoLink, в частности, должен сгенерировать исполняемый файл из используемого вами кода. Вы можете создать консольное приложение Win32 с точкой _start
входа таким образом:
nasm -fwin32 learn.asm -o learn.obj
golink /console /entry _start learn.obj
GoLink создаст исполняемый файл с соответствующими заголовками и разделами, с которыми у Windows не должно возникнуть проблем при запуске без необходимости добавления .rdata
раздела.
Если у вас установлен MSVC / C , вы также можете использовать компоновщик Microsoft:
nasm -fwin32 learn.asm -o learn.obj
link learn.obj /entry:start /subsystem:console
Комментарии:
1. Фоном, похоже, является раздел «.idata» (который, кстати, не должен называться «.idata»): если
ld
используется так, как это сделал OP, код запуска не используется, поэтому точка входа_main
(или_start
, если функция названатаким образом). Поскольку программа должна вызывать ОС (по крайней мере, дляexit
редактирования), а единственная надежная (и разрешенная) возможность вызова ядра Windows — это использование DLL, программа должна использовать DLL. Возврат usingret
из кода точки входа не разрешен ни в Windows, ни в Linux.2. @MartinRosenau: процесс Win32 может завершиться, если основной поток возвращается со
ret
значением, если и только если основной поток является единственным активным потоком.3. Если загрузчик Windows когда-либо создавал более одного потока, возможно, это
ret
не приведет к завершению процесса. Общее эмпирическое правило, однако, чтобы избежать этой проблемы, нужно вызвать ExitProcess . Я сам не из тех, кто используетret
подобное.4. Интересно. Однако я заметил, что многие версии Windows отказывались загружать исполняемый файл, если в разделе импорта не было указано ни одного DLL-файла. Windows Vista или Windows 7 (я не уверен) просто ничего не делает, если EXE-файл не содержит импорта: код не выполняется, но программа возвращается сразу. Вы можете проверить это, запрограммировав бесконечный цикл или некоторый код, который вызывает исключение. Я могу себе представить, что Windows 10 печатает сообщение об ошибке, указанное в вопросе, вместо того, чтобы «молча» ничего не делать.