16bit / ASM:使用int 21h的简单功能?

时间:2012-05-01 09:02:54

标签: assembly x86 dos

为什么我的'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!$'

3 个答案:

答案 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!$"