2012-05-01 52 views
0

爲什麼我的'show_msg'功能不能正常工作?16bit/ASM:使用int 21h的簡單函數?

org 100h 

push str1 
call show_msg 
pop ax 

mov ah, 4Ch 
int 21h 

show_msg: 
mov ah, 9 
mov bx, sp ;in 16bit bx is the only register that can act as a pointer (besides di and si) 
mov dx, [bx] 
int 21h 
ret 


str1 db 'Hello world!$' 
+0

在哪臺機器和操作系統應該正常工作? – ShinTakezou

+0

在16位DOS上... – user1091856

回答

4

最有可能是因爲[sp]在進入該功能包含返回代碼,它的地址 - 在這個節目的情況下 - 將是在開始任何地址pop ax下。嘗試將mov dx, [bx]更改爲mov dx, [bx+2],這將導致在檢索函數入口之前推送的參數值。

1

你的代碼有一個基本缺陷。

首先,bp也可以用作指針。

您應該使用bp寄存器而不是bx寄存器來索引堆棧。 [bp]表單默認使用SS分段,而[bx]表單使用DS作爲默認分段。這意味着如果你使用[bx]但是其他一些未定義的值,那麼如果DS!= SS,你將會得到而不是

所以,正確的版本是: -

show_msg: 
    mov bp,sp 
    mov ah,9 
    mov dx,[bp+2] 
    int 21h 
    ret 

如果函數需要一些本地存儲,那麼一般形式是: -

function: 
    mov bp,sp 
    sub sp,amount of space for local storage 

    some code, parameters are [bp+offset], local data are [bp-offset] 

    mov sp,bp 
    ret 
+0

+1。我沒有做過很多實模式編程,所以我傾向於忘記一些寄存器具有分配給它們的「默認」段。感謝您分類。 –

0

因爲DX所做的計劃將無法正常工作NOT指向「str1」的地址。

首先,將str1的地址壓入SP指向的堆棧中。這是沒有問題的。

但是,在調用函數「show_str」來打印str1後,SP將不再指向str1,因爲原始IP的值將被壓入堆棧中,SP指向該堆棧。

你沒有意識到SP的改變,仍然試圖將SP的值傳遞給DX,DX應該存儲要打印的字符串的地址。

我的建議是,您應該使用「正常」風格來編寫程序,因爲除非您正在探索語言本身的祕密,否則這會讓我們的生活更輕鬆。

這是我的程序。

;file: showmsg.asm (.COM) 
    ;nasm -fbin showmsg.asm -o showmsg.com 

    org 0x100 
    mov ax, cs 
    mov ds, ax 

    mov ax, str1  ;Transmit parameter to show_msg through AX 
    call show_msg 

mov ax, 4c00h 
int 21h 

show_msg:   ;the address offset of the string is stored in ax 
    mov dx, ax  ;DS:DX=string address 
    mov ax, 0900h ;AH=09 
    int 21h 
    ret 
str1: db "Hello, world!$"