DOS Interrupt in masm x86-Assembler abstürzt
Frage
Ich habe gerade damit begonnen, auf win32 einig x86-Assembler zu lernen, und ich habe masm mit Visual Studio 2008 mit der benutzerdefinierten Buildregel verwendet, die für .asm Dateien mit dem ide kommt. Ich habe versucht, das DOS zu verwenden, unterbrechen, um die Konsole zu drucken, sondern erhalte ich die Meldung: „Nicht behandelte Ausnahme bei 0x00401004 in ASMTest.exe: 0xC0000005: Zugriffsverletzung Leseort 0xffffffff.“ auf der 8. Zeile. Ich versuche, das einzelne ASCII-Zeichen 'A' (41h) Hier ist der masm Code zur Ausgabe:
.386
.MODEL flat, stdcall
.CODE
start:
mov dl, 41h
mov ah, 2
int 21h
ret
end start
Wenn ich debug.exe, und verwenden Sie den ‚a‘ Befehl zur Eingabe aller .CODE Anweisungen, und führen Sie es ( ‚g‘), es funktioniert gut.
Kann jemand mich aufklären, wie richtig die DOS-Interrupt zu bedienen? Dank!
EDIT: Wenn auf dem Win32-Programmierung, Managu richtig ist, dass Sie einen Windows-API-Aufruf wie WriteConsoleA stattdessen das DOS-Interrupt der Verwendung verwendet werden sollen. Diese eine hilfreiche Ressource war. Sollte diese (wie ich war) jemand für den Code ist auf der Suche zu tun, hier ist es:
.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
(Stellen Sie den Einstiegspunkt zur Haupt)
Lösung
Wenn Sie debug.exe zur Eingabe von diesen Code verwenden, sind Zusammenbauen Sie eine 16-Bit (8086 Architektur, "real mode") DOS-Programm. Die Semantik Sie sind für ein solches Programm korrekt angeben. Wenn Sie jedoch das Programm zusammenstellen, Sie haben hier mit MASM bekommen, und dann verknüpfen, sind Sie eine 32-Bit zu erstellen versuchen, Windows-Programm (i386-Architektur „-Modus geschützt“). Ich konnte irren, aber ich glaube nicht, können Sie rechtlich auch int 21h im letzteren Fall aufrufen.
Andere Tipps
Es ist möglich, dass es wegen Ihrer ‚ret‘ Anweisung auftritt. Wo kehren Sie zu? Ein unbekannter Ort in Erinnerung, ich stelle mir vor.
Stattdessen versuchen int 20h verwenden. Das wird "anmutig." Beenden
Es funktioniert im Debug (wahrscheinlich), denn das ist eine "managed" -Umgebung.
Wenn wir eine 16-Bit-DOS starten - *. Com Anwendung, dann füllt DOS den Opcode einer „int 20“ Anweisung innerhalb unseres PSP bei 0 versetzt und zusätzliches DOS ein Wort mit Null auf unserem Stapel schieben, bevor DOS ließ unsere Anwendung auszuführen. So können wir eine einfache „ret“ Anweisung am Ende unseres Codes platzieren. Aber wir müssen sicherstellen, dass unsere Stackpointer nicht beschädigt sind und unser Codesegment wird nicht verändert.
Für eine 16-Bit-Anwendung zu verknüpfen MASM mit 6+ wir ein 16-Bit-Linker benötigen.
ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe
Dirk