2009-09-12 4 views
3

Я только начал изучать некоторые сборки x86 на win32, и я использовал masm с visual studio 2008, используя правило пользовательской сборки, которое поставляется с идеей для файлов .asm. Я пытаюсь использовать прерывание DOS для печати на консоль, но вместо этого получаю сообщение: «Необработанное исключение в 0x00401004 в ASMTest.exe: 0xC0000005: место чтения нарушения прав доступа 0xffffffff». на 8-й линии. Я пытаюсь вывести одного символа ASCII «A» (41h) Вот код MASM:DOS Прерывание в сбое сборки masm x86

.386 
.MODEL flat, stdcall 

.CODE 
start: 
    mov dl, 41h 
    mov ah, 2 
    int 21h 
    ret 
end start 

Когда я использую Debug.exe и использовать команду «а», чтобы ввести все инструкции .Code, и запустите его («g»), он отлично работает.

Может ли кто-нибудь просветить меня о том, как правильно использовать прерывание DOS? Благодаря!

EDIT: При программировании на win32, Managu является правильным, что вы должны использовать вызов windows api, например WriteConsoleA, вместо использования прерывания DOS. This был полезным ресурсом. В случае, если кто-то ищет код, чтобы сделать это (как я), вот это:

.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 

(Установить точку входа в основной)

ответ

3

Когда вы используете debug.exe для ввода этого кода, вы собираете 16-разрядную (8086-архитектуру, «реальный режим») dos-программу. Выбранная семантика верна для такой программы. Однако, когда вы собираете программу, которую вы получили здесь с MASM, а затем связываете ее, вы пытаетесь создать 32-разрядную (i386-архитектуру, «защищенный режим») программу Windows. Я мог ошибаться, но я не думаю, что вы можете юридически даже вызвать int 21h в последнем случае.

+0

@unknown: вы даже сказать, MASM, чтобы создать 32-битный исполняемый файл для вас ('.MODEL flat') –

0

Вполне возможно, что это происходит из-за вашего «RET 'инструкции. Куда вы возвращаетесь? Полагаю, какое-то неизвестное место в памяти.

Вместо этого попробуйте использовать int 20h. Это выйдет «изящно».

Он работает в отладке (возможно), потому что это более «управляемая» среда.

0

Если мы начинаем 16-битное приложение DOS - *. Com, то DOS заполняет код операции «int 20» внутри нашей PSP со смещением 0 и дополнительным DOS нажимаем слово с нулем в нашем стеке до того, как DOS let наше приложение выполняется. Поэтому мы можем поместить простую инструкцию «ret» в конце нашего кода. Но мы должны убедиться, что наш стек не поврежден, а наш код не изменен.

Для связи 16-разрядного приложения с использованием MASM 6+ нам нужен 16-битный компоновщик.

ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe

Dirk

Смежные вопросы