为什么我的“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!$'
很可能是因为[sp]在进入函数时包含返回代码的地址,在这个程序的情况下,它将是pop ax开头的任何地址。尝试更改mov dx, [bx]为mov dx, [bx+2],这将导致在函数条目之前推送的参数的值被检索。
您的代码存在根本缺陷。
首先,bp 也可以用作指针。
您应该使用 bp 寄存器而不是 bx 寄存器来索引堆栈。[bp] 形式默认使用 SS 段,而 [bx] 形式使用 DS 作为默认段。这意味着如果 DS != SS 如果您使用 [bx] ,您将不会读取压入堆栈的值,而是使用其他一些未定义的值。
所以,正确的版本是:-
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
该程序将无法正常运行,因为 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!$"