Прерывание DOS при сбое сборки masm x86
Вопрос
Я только начал изучать сборку x86 на Win32 и использовал masm с Visual Studio 2008, используя пользовательское правило сборки, которое поставляется с ide для файлов .asm.Я пытался использовать прерывание DOS для печати на консоли, но вместо этого получаю сообщение:«Необработанное исключение по адресу 0x00401004 в ASMTest.exe:0xC0000005:Нарушение прав доступа при чтении местоположения 0xffffffff.» в 8-й строке.Я пытаюсь вывести один символ ascii «A» (41h). Вот код masm:
.386
.MODEL flat, stdcall
.CODE
start:
mov dl, 41h
mov ah, 2
int 21h
ret
end start
Когда я использую debug.exe и использую команду «a» для ввода всех инструкций .CODE и запускаю ее («g»), все работает нормально.
Может ли кто-нибудь просветить меня, как правильно использовать прерывание DOS?Спасибо!
РЕДАКТИРОВАТЬ:При программировании на Win32 Манагу прав в том, что вам следует использовать вызов Windows API, например WriteConsoleA, вместо использования прерывания DOS. Этот был полезным ресурсом.Если кто-то ищет код для этого (как я), вот он:
.386
.MODEL flat, stdcall
; Windows API prototypes
GetStdHandle proto :dword
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
ExitProcess proto :dword
STD_OUTPUT_HANDLE equ -11
.DATA
HelloWorldString db "hello, world", 10, 0
.CODE
strlen proc asciiData:dword
; EAX used as count, EBX as ascii char pointer, EDX (DL) as ascii char
mov eax, -1
mov ebx, asciiData
mov edx, 0
BeginLoop:
inc eax ; ++count (init is -1)
mov dl, [ebx] ; *dl = *asciiptr
inc ebx ; ++asciiptr
cmp dl, 0 ; if (*dl == '\0')
jne BeginLoop ; Goto the beginning of loop
ret
strlen endp
main proc
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov ecx, eax
invoke strlen, addr HelloWorldString
invoke WriteConsoleA, ecx, addr HelloWorldString, eax, 0, 0
ret
main endp
end
(Установите точку входа как главную)
Решение
Когда вы используете debug.exe для ввода этого кода, вы собираете 16-разрядную (8086 архитектура, "реальный режим") программу DOS. Указанная вами семантика верна для такой программы. Тем не менее, когда вы собираете программу с MASM, а затем связываете ее, вы пытаетесь создать 32-разрядную (архитектура i386, «защищенный режим») программу для Windows. Я могу ошибаться, но я не думаю, что вы можете по закону даже вызывать int 21h в последнем случае.
Другие советы
Возможно, это происходит из-за вашей инструкции 'ret'. Куда ты возвращаешься? Я полагаю, какое-то неизвестное место в памяти.
Вместо этого попробуйте использовать int 20h. Это выйдет "изящно".
Он работает в режиме отладки (вероятно), потому что это более "управляемый" процесс. окружающая среда.
Если мы запускаем 16-битное приложение DOS-*.com, то DOS заполняет код операции инструкции «int 20» внутри нашего PSP со смещением 0, а дополнительный DOS помещает слово с нулем в наш стек, прежде чем DOS разрешит нашему приложению выполниться.Таким образом, мы можем разместить простую инструкцию «ret» в конце нашего кода.Но мы должны убедиться, что наш указатель стека не поврежден и наш кодовый сегмент не изменен.
Чтобы связать 16-битное приложение с помощью MASM 6+, нам нужен 16-битный компоновщик.
ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe
Дирк