Pergunta

Eu apenas comecei a aprender algumas x86 montagem em win32, e eu usei masm com visual studio 2008 usando a regra de compilação personalizada que vem com o IDE para arquivos .asm. Eu tenho tentado usar a interrupção DOS para imprimir para o console, mas em vez disso eu recebo a mensagem: "Excepção no 0x00401004 em ASMTest.exe: 0xC0000005: Violação de acesso leitura local 0xffffffff." na linha 8ª. Estou tentando saída o caractere ASCII single 'A' (41h) Aqui está o código masm:

.386
.MODEL flat, stdcall

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

Quando eu uso debug.exe, e usar o 'a' comando para entrada todas as instruções .CODE, e executá-lo ( 'g'), ele funciona bem.

Alguém pode me esclarecer sobre como usar o DOS interromper corretamente? Obrigado!

EDIT: Ao programar em win32, Managu é certo que você deve usar uma chamada API do Windows como WriteConsoleA em vez de usar a interrupção DOS. Este foi um recurso útil. No caso de alguém está olhando para o código para fazer isso (como eu estava), aqui está:

.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

(Set o ponto de entrada principal)

Foi útil?

Solução

Quando você usa debug.exe para entrar este código, você está montando um de 16 bits (8086 arquitetura, "modo real") dos programas. A semântica especificadas estão corretas para esse programa um. No entanto, quando você monta o programa que temos aqui com MASM, e depois ligá-lo, você está tentando criar um 32-bit programa do Windows (i386 arquitetura, "modo protegido"). Eu poderia estar enganado, mas eu não acho que você pode legalmente mesmo invocar 21h int neste último caso.

Outras dicas

É possível que isso ocorre por causa de sua instrução 'ret'. Onde estão voltando para? Algum lugar desconhecido na memória, eu imagino.

Em vez disso, tente usar int 20h. Isso vai sair "graciosamente".

Ele funciona de depuração (provavelmente) porque é um ambiente mais "administrado".

Se começarmos a 16 bit DOS -. * Aplicativo com, então DOS preencher o código de operação de um "int 20" dentro de instrução do nosso PSP no deslocamento 0 e DOS adicional empurrar uma palavra com zero na nossa pilha antes DOS deixar nossa aplicação executar. Assim, podemos colocar um simples instrução "ret" no final do nosso código. Mas temos que ter certeza de que o nosso stackpointer não está corrompido e nossa codesegment não é alterado.

Para vincular um aplicativo de 16 bits usando MASM 6+ precisamos de um vinculador de 16 bits.

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

Dirk

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top