Interruption DOS dans un crash de l'assembly masm x86
Question
Je viens tout juste de commencer à apprendre l'assemblage x86 sur win32 et j'ai utilisé masm avec Visual Studio 2008 à l'aide de la règle de construction personnalisée fournie avec le fichier ide pour les fichiers .asm. J'ai essayé d'utiliser l'interruption DOS pour imprimer sur la console, mais je reçois le message suivant: "Exception non gérée à 0x00401004 dans ASMTest.exe: 0xC0000005: emplacement de lecture de la violation d'accès 0xffffffff." à la 8ème ligne. J'essaie de générer le caractère ascii simple 'A' (41h) Voici le code masm:
.386
.MODEL flat, stdcall
.CODE
start:
mov dl, 41h
mov ah, 2
int 21h
ret
end start
Lorsque j'utilise debug.exe et que j'utilise la commande 'a' pour saisir toutes les instructions .CODE et que je l'exécute ('g'), cela fonctionne correctement.
Quelqu'un peut-il m'expliquer comment utiliser correctement l'interruption DOS? Merci!
EDIT: Lors de la programmation sur win32, Managu a raison de vous demander d’utiliser un appel api Windows tel que WriteConsoleA au lieu d’utiliser l’interruption DOS. Cette était une ressource utile. Si quelqu'un cherche le code pour le faire (comme je l'étais), le voici:
.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
(Définissez le point d'entrée sur principal)
La solution
Lorsque vous utilisez debug.exe pour saisir ce code, vous assemblez un programme dos 16 bits (architecture 8086, "mode réel"). La sémantique que vous spécifiez est correcte pour un tel programme. Cependant, lorsque vous assemblez le programme que vous avez ici avec MASM, puis que vous le liez, vous essayez de créer un programme Windows 32 bits (architecture i386, "en mode protégé"). Je peux me tromper, mais je ne pense pas que vous puissiez légalement même invoquer int 21h dans ce dernier cas.
Autres conseils
Il est possible que cela se produise à cause de votre instruction 'ret'. Où reviens-tu? Un endroit inconnu en mémoire, j'imagine.
Au lieu de cela, essayez d'utiliser int 20h. Cela se termine "gracieusement".
Cela fonctionne en mode débogage (probablement) car il s'agit d'un fichier "& géré; géré" " environnement.
Si nous lançons une application DOS - *. com 16 bits, alors DOS remplira le code opération d'un "int 20". instruction dans notre PSP à l'offset 0 et DOS supplémentaire poussant un mot avec zéro sur notre pile avant que DOS ne laisse notre application s'exécuter. Nous pouvons donc placer un simple " ret " instruction à la fin de notre code. Mais nous devons nous assurer que notre stackpointer n’est pas corrompu et que notre segment de code n’est pas modifié.
Pour lier une application 16 bits à l'aide de MASM 6+, nous avons besoin d'un éditeur de liens 16 bits.
ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe
Dirk