Pregunta

Acabo de comenzar a aprender algo de ensamblaje x86 en win32, y he usado masm con Visual Studio 2008 usando la regla de compilación personalizada que viene con la ide para archivos .asm. He estado tratando de usar la interrupción de DOS para imprimir en la consola, pero en su lugar recibo el mensaje: "Excepción no controlada en 0x00401004 en ASMTest.exe: 0xC0000005: Ubicación de lectura de violación de acceso 0xffffffff". en la 8va línea. Estoy tratando de generar el carácter ascii único 'A' (41h) Aquí está el código masm:

.386
.MODEL flat, stdcall

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

Cuando uso debug.exe, y uso el comando 'a' para ingresar todas las instrucciones .CODE, y lo ejecuto ('g'), funciona bien.

¿Puede alguien aclararme cómo usar la interrupción de DOS correctamente? Gracias!

EDITAR: Al programar en win32, Managu tiene razón en que debe usar una llamada de API de Windows como WriteConsoleA en lugar de usar la interrupción de DOS. Esto fue un recurso útil. En caso de que alguien esté buscando el código para hacer esto (como yo estaba), aquí 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

(Establecer el punto de entrada como principal)

¿Fue útil?

Solución

Cuando usa debug.exe para ingresar este código, está ensamblando un programa DOS de 16 bits (arquitectura 8086, " modo real "). La semántica que especifique es correcta para dicho programa. Sin embargo, cuando ensambla el programa que tiene aquí con MASM, y luego lo vincula, intenta crear un programa de Windows de 32 bits (arquitectura i386, "modo protegido"). Podría estar equivocado, pero no creo que pueda invocar legalmente int 21h en este último caso.

Otros consejos

Es posible que ocurra debido a su instrucción 'ret'. ¿A dónde regresas? Algún lugar desconocido en la memoria, me imagino.

En su lugar, intente usar int 20h. Eso saldrá " con gracia. & Quot;

Funciona en depuración (probablemente) porque es más "administrado" medio ambiente.

Si iniciamos una aplicación DOS - *. com de 16 bits, entonces DOS llena el código de operación de un " int 20 " instrucción dentro de nuestro PSP en el desplazamiento 0 y DOS adicional empuja una palabra con cero en nuestra pila antes de que DOS permita que nuestra aplicación se ejecute. Entonces podemos colocar un simple "ret" instrucciones al final de nuestro código. Pero tenemos que asegurarnos de que nuestro stackpointer no esté dañado y nuestro segmento de código no cambie.

Para vincular una aplicación de 16 bits usando MASM 6+ necesitamos un vinculador de 16 bits.

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

Dirk

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top