为什么我的'show_msg'功能不正常?
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 :(得分:4)
最有可能因为[sp]
在进入函数时包含返回代码的地址,在这个程序的情况下,它将是开头的任何地址pop ax
。尝试将mov dx, [bx]
更改为mov dx, [bx+2]
,这将导致在检索函数条目之前推送的参数值。
答案 1 :(得分: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
答案 2 :(得分:0)
程序无法正常工作,因为DX不指向“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!$"