2009-09-12 57 views
3

我剛剛開始在win32上學習一些x86程序集,並且我已經使用ide for .asm文件附帶的自定義構建規則在Visual Studio 2008中使用了masm。我一直在嘗試使用DOS中斷打印到控制檯,但是我收到消息:「ASMTest.exe中0x00401004處未處理的異常:0xC0000005:訪問衝突讀取位置0xffffffff。」在第八行。我試圖輸出單個ASCII字符「A」(41H)這裏是MASM代碼:DOS中斷masm x86程序集崩潰

.386 
.MODEL flat, stdcall 

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

當我使用Debug.exe將,並用「A」命令輸入所有.CODE指令,並運行它('g'),它工作正常。

任何人都可以啓發我如何正確使用DOS中斷嗎?謝謝!

編輯:當在win32上編程時,Managu是正確的,你應該使用像WriteConsoleA的Windows API調用,而不是使用DOS中斷。 This是一個有用的資源。如果有人正在尋找的代碼來做到這一點(像我),那就是:

.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 

,這是因爲你的「RET的(設置的入口點主)

回答

3

當您使用debug.exe輸入此代碼時,您正在組裝一個16位(8086架構,「實模式」)dos程序。您指定的語義對於這樣的程序是正確的。但是,當您將MASM中的程序組裝到此處時,然後將其鏈接起來,則會嘗試創建一個32位(i386體系結構,「受保護模式」)Windows程序。我可能會誤解,但我認爲你在後一種情況下甚至可以合法地調用int 21h。

+0

@unknown:你甚至告訴MASM爲您創造一個32位可執行文件('.MODEL flat') – 2009-09-12 05:19:32

0

這是可能的'指示。你在哪裏回來?我想象的是記憶中一些不爲人知的地方。

而是嘗試使用int 20h。那將會「優雅地」退出。

它工作在調試(可能),因爲這是一個更「管理」的環境。

0

如果我們啓動一個16位的DOS - *。com應用程序,那麼DOS在我們的PSP內部的偏移量爲0處填充「int 20」指令的操作碼,並且在DOS之前,額外的DOS在我們的堆棧上推零字我們的程序執行所以我們可以在代碼末尾放置一個簡單的「ret」指令。但是我們必須確保我們的堆棧指針沒有被破壞,並且我們的代碼段沒有被改變。

對於使用MASM 6+鏈接16位應用程序,我們需要一個16位鏈接器。

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

德克