从汇编代码打印字符串时出错

时间:2016-06-06 06:58:30

标签: assembly emu8086 x86-16

我是汇编新手,我关注的课程使用 EMU8086 。我写了这段代码来打印Testing和ASCII码50,它是数字2,但它只打印Testing并忽略其余的。怎么了?

.model tiny
.code

org 100h


main proc

    mov ah, 09h
    mov dx, offset msg
    int 21h 
    mov ah, 4ch
    mov dx ,0  
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main

在阅读@ 500 - 内部服务器错误的评论后,我将我的代码更新为:

.model tiny
.code

org 100h


main proc

    mov ah, 09h
    mov dx, offset msg
    int 21h 
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main

它仍然无法正常工作,那有什么不对?

2 个答案:

答案 0 :(得分:1)

DOS 中断INT 21h/AH=9h不会打印字符值,它会将内存偏移量移到要打印的procedure TForm1.LoadFile(const AFilename: String); var I: TIniFile; L: TStringList; X: Integer; N: String; V: String; begin I:= TIniFile.Create(AFilename); try L:= TStringList.Create; try ComboBox1.Items.Clear; I.ReadSectionValues('Colours', L); for X := 0 to L.Count-1 do begin N:= L.Names[X]; //The Name V:= L.Values[N]; //The Value ComboBox1.Items.Add(V); end; finally L.Free; end; finally I.Free; end; end; 终止字符串的开头。

  

DOS 1+ - 写入标准输出字符串

     

AH = 09h

     

DS:DX - > '$' - 终止字符串

     

返回:

     

AL = 24h('$'终止字符串,尽管官方文档声明没有返回任何内容)(至少DOS 2.1-7.0和NWDOS)

如果要使用 INT 21h / AH = 9h 打印单个字符,则需要将值移动到以$符号终止的缓冲区中。然后,将该缓冲区的地址传递给 INT 21h / AH = 9h 。根据你的第二个例子,这样的事情应该有效:

$

而不是.model tiny .code org 100h main proc mov ah, 09h ; DOS Interrupt ah=9h print $ terminated string mov dx, offset msg ; Address of msg int 21h ; Int 21h/ah=9h Print msg mov outchar, 48+2 ; Move ASCII val for `2` to outchar buffer mov dx, offset outchar ; Address of the $ terminated outchar buffer in DX int 21h ; AH is still 9h, so this prints $ terminated string mov ax, 4c00h ; Exit program with return value 0 int 21h endp msg db "Testing$" ; msg string outchar db ?, "$" ; output buffer for single character terminated with $ end main 你可以像这样使用ASCII值:

mov outchar, 48+2

或者你可以通过一次调用 INT 21h / AH = 9h 来做到这一点,方法是将你想要的字符放在输出缓冲区的中间:

mov outchar, '2'

这样做的原因是因为 INT 21h / AH = 9h 将盲目地打印从偏移main proc mov outchar, '2' ; Place the ASCII value for '2' in the output buffer mov ah, 09h mov dx, offset msg int 21h ; Print $ terminated string starting at `msg` mov ax, 4c00h int 21h ; Exit with error code 0 endp msg db "Testing" outchar db ?, "$" 开始找到的所有内容,直到找到msg终止字符。我们首先在$处有效地替换字符,这样当 INT 21h / AH = 9h 执行时,它将在内存中遇到outchar

一旦到达Testing2$,它将停止打印,因此输出将如下所示:

  

Testing2

您还可以选择使用两个不同的DOS(INT 21h)中断。当 INT 21h / AH = 9h 打印一个$终止的字符串时,INT 21h/AH=2h会显示一个字符:

  

DOS 1+ - 标准输出的写字符

     

AH = 02h

     

DL =要写的字符

     

返回:   AL =最后一个字符输出(尽管官方文档说明了   什么都没有返回)(至少DOS 2.1-7.0)

您可以将程序编码为显示$字符串,但之后您可以使用 INT 21h / AH = 2h 来显示单个字符。您的代码可能如下所示:

msg

答案 1 :(得分:1)

您的第二个代码几乎没问题,您只忘记ah中的服务号码,告诉int 21h该做什么:

.model tiny
.code

org 100h


main proc

    mov ah, 09h
    mov dx, offset msg
    int 21h 

    mov ah, 2          ;<==== AH=2 : INT 21H WILL DISPLAY CHARACTER IN DL.
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main