assemblyiox86masm32

using IN instruction crashes the x86 program


I am trying to write a delay timer using port 61H (PB4) and using MASM run it on a Windows XP on virtual machine. However, when the code runs the IN instruction, it crashes the program, no matter which port is called.

.386
.model flat,stdcall


include C:\masm32\include\windows.inc
include C:\masm32\include\masm32.inc
include C:\masm32\include\msvcrt.inc
include C:\masm32\include\kernel32.inc
includelib C:\masm32\lib\masm32.lib
includelib C:\masm32\lib\msvcrt.lib
includelib C:\masm32\lib\kernel32.lib

.data
msg1 db "text 1  ", 0
msg2 db "text 2", 0
msg3 db "text 2", 0

.code
start proc

invoke crt_printf, offset msg1
push cx

call waitf
pop cx

invoke crt_printf, offset msg2

invoke crt_scanf, offset msg3
invoke ExitProcess,0

start endp


waitf proc near
    mov cx, 33144
    push ax
    waitf1:
        in al, 61h
        and al, 10h
        cmp al, ah  
        je waitf1   
        mov ah, al
        loop waitf1
        pop ax  
        ret
waitf endp

end start

I can not understand why the computer can not get data from the port 61h.


Solution

  • Computer can get data from I/O port but only if it runs in real mode or in ring 0, which is reserved for kernel and device drivers. In native DOS you can read whichever I/O port you like, and some well-known ports can be read/written even when the realmode program runs in simulator (NTVDM, DosBox).

    But as you have chosen Windows protected-mode executable, this won't work.
    Invoke WinAPI function Sleep(dwMilliseconds) instead.