Interrupción de DOS en el ensamblaje masm x86 que falla
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)
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