DOS Interrupt в сбое сборки masm x86 - PullRequest
       29

DOS Interrupt в сбое сборки masm x86

3 голосов
/ 12 сентября 2009

Я только начал изучать некоторые сборки 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

(установить точку входа на главную)

Ответы [ 3 ]

3 голосов
/ 12 сентября 2009

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

0 голосов
/ 05 мая 2013

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

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

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

Dirk

0 голосов
/ 12 сентября 2009

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

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

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

...