Domanda

Ho appena iniziato a studiare alcuni assembly x86 su win32 e ho usato masm con Visual Studio 2008 usando la regola di generazione personalizzata fornita con l'ide per i file .asm. Ho provato a utilizzare l'interrupt DOS per stampare sulla console, ma invece ricevo il messaggio: " Eccezione non gestita a 0x00401004 in ASMTest.exe: 0xC0000005: Accedi alla posizione di lettura della violazione 0xffffffff. & Quot; sull'ottava riga. Sto cercando di emettere il singolo carattere ASCII 'A' (41h) Ecco il codice MASM:

.386
.MODEL flat, stdcall

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

Quando uso debug.exe e utilizzo il comando 'a' per inserire tutte le istruzioni .CODE ed eseguirlo ('g'), funziona benissimo.

Qualcuno può illuminarmi su come usare correttamente l'interrupt DOS? Grazie!

EDIT: durante la programmazione su win32, Managu ha ragione a usare una chiamata api Windows come WriteConsoleA invece di usare l'interrupt DOS. Questa è stata una risorsa utile. Nel caso in cui qualcuno stia cercando il codice per farlo (come ero io), eccolo qui:

.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

(Imposta il punto di ingresso su principale)

È stato utile?

Soluzione

Quando usi debug.exe per inserire questo codice, stai assemblando un programma dos a 16 bit (architettura 8086, "modalità reale"). La semantica specificata è corretta per tale programma. Tuttavia, quando assembli il programma che hai qui con MASM e poi lo colleghi, stai provando a creare un programma Windows a 32 bit (architettura i386, "modalità protetta"). Potrei sbagliarmi, ma non credo che tu possa nemmeno invocare legalmente int 21h in quest'ultimo caso.

Altri suggerimenti

È possibile che si verifichi a causa delle tue istruzioni 'ret'. Dove stai tornando? Qualche posto sconosciuto nella memoria, immagino.

Invece, prova a usare int 20h. Questo uscirà "con grazia."

Funziona in debug (probabilmente) perché è più " gestito " ambiente.

Se iniziamo un'applicazione DOS - *. com a 16 bit, allora DOS riempie il codice operativo di un " int 20 " istruzioni all'interno della nostra PSP a offset 0 e DOS aggiuntivo inviano una parola con zero sul nostro stack prima che DOS esegua la nostra applicazione. Quindi possiamo inserire un semplice "ret" istruzioni alla fine del nostro codice. Ma dobbiamo assicurarci che il nostro stackpointer non sia danneggiato e che il nostro segmento di codice non sia cambiato.

Per collegare un'applicazione a 16 bit usando MASM 6+ abbiamo bisogno di un linker a 16 bit.

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

Dirk

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top